C#: как передать null функции, ожидающей ref?
у меня есть следующая функция:
public static extern uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    ref Mapping oMapping,
    out byte PagesPerSector);
который я хотел бы назвать так:
FILES_GetMemoryMapping(MapFile, out size, MapName,
    out PacketSize, null, out PagePerSector);
к сожалению, я не могу пройти null в поле, для которого требуется тип ref Mapping и никакой бросок я не пробовал исправить это.
какие предложения?
6 ответов
Я предполагаю, что отображение является структурой?  Если это так, вы можете иметь две версии FILES_GetMemoryMapping() прототип с разными сигнатурами. Для второй перегрузки, где вы хотите пройти null, выберите параметр IntPtr и использовать IntPtr.Zero
public static extern uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    IntPtr oMapping,
    out byte PagesPerSector);
вызов пример:
FILES_GetMemoryMapping(MapFile, out size, MapName,
   out PacketSize, IntPtr.Zero, out PagePerSector);
если сопоставление на самом деле является классом, а не структурой, просто установите значение null перед его передачей.
причина, по которой вы не можете пройти null, потому что ref параметр получает специальную обработку компилятором C#.  Любой ref параметр должен быть ссылкой, которая может быть передана вызываемой функции.  Так как вы хотите пройти null компилятор отказывается разрешить это, так как вы не предоставляете справку о том, что функция ожидает получить.
ваш единственный реальный вариант-создать локальную переменную, установите его в null, и передать это.  Этот компилятор не позволит вам сделать гораздо больше.
Mapping oMapping = null;
FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, ref oMapping, out PagePerSector);
а @JaredPar это ответ несомненно правильно ответ тут другое ответ: unsafe код и указатели:
unsafe {
    Mapping* nullMapping = null;
    FILES_GetMemoryMapping(
            MapFile,
            out size,
            MapName,
            out PacketSize,
            ref *nullMapping,    // wat?
            out PagePerSector);
}
это выглядит как будто это должно произойти во время выполнения, но это не так, потому что ref и * компенсируют друг друга и результирующее значение ref *nullMapping является нулевым указателем, который является то, что FILES_GetMemoryMapping() получит для этого параметра.
это, вероятно, не хорошая идея!--10-->, но это возможно.
возможно, это не совсем идеальный ответ, но если вам нужно передать null в качестве параметра при вызове функции, подумайте о перегрузке этой функции, которая опускает формальный параметр для переменной, которую вы пытаетесь установить в null.
например, скажем, у вас есть функция, которая выглядит так:
public void MyFunction(string x, int y, ref string z) {...};
вы хотите иметь возможность передавать null для параметра z. Попробуйте вместо этого создать новый MyFunction перегрузка, которая выглядит примерно так это:
public void MyFunction(string x, int y) {...};
этот подход не будет соответствовать потребностям каждого, но это еще одно возможное решение.
