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, и передать это. Этот компилятор не позволит вам сделать гораздо больше.


один из способов-создать фиктивную переменную, присвоить ей значение 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) {...};

этот подход не будет соответствовать потребностям каждого, но это еще одно возможное решение.