C#:如何将null传递给期望ref的函数?

我有以下function:

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); 

不幸的是,我不能在需要类型ref Mapping的字段中传递null而且没有强制转换我已尝试修复此问题。

有什么建议?

我假设Mapping是一个结构? 如果是这样,您可以使用具有不同签名的两个版本的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); 

如果Mapping实际上是一个类而不是一个结构,只需将值设置为null,然后再将其传递给它。

无法传递null的原因是因为C#编译器对ref参数给予了特殊处理。 任何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()将为该参数接收的。

这可能不是一个好主意 ,但它是可能的

也许它不完全是理想的答案,但是如果在调用函数时需要传递null作为参数,请考虑对该函数进行重载,省略您尝试设置为null的变量的forms参数。

例如,假设您有一个如下所示的函数:

 public void MyFunction(string x, int y, ref string z) {...}; 

您希望能够为参数z传递null。 尝试创建一个新的MyFunction重载,看起来像这样:

 public void MyFunction(string x, int y) {...}; 

这种方法不适合每个人的需求,但这是另一种可能的解决方案。