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

时间:2009-04-10 01:48:35

标签: c# null pinvoke parameters 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而且我没有尝试修改此问题。

有什么建议吗?

7 个答案:

答案 0 :(得分:30)

我假设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。

答案 1 :(得分:25)

您无法传递null的原因是因为C#编译器对ref参数进行了特殊处理。任何ref参数都必须是可以传递给您正在调用的函数的引用。由于你想传​​递null,编译器拒绝允许这样做,因为你没有提供函数期望的引用。

你唯一真正的选择是创建一个局部变量,将其设置为null,然后传入。编译器不允许你做更多的事情。

答案 2 :(得分:9)

一种方法是创建一个虚拟变量,将其赋值为null,并将其传递给。

答案 3 :(得分:4)

Mapping oMapping = null;

FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, ref oMapping, out PagePerSector);

答案 4 :(得分:1)

虽然@ JaredPar的answer无疑是正确的答案,但还有另一个答案:unsafe代码和指针:< / p>

unsafe {
    Mapping* nullMapping = null;
    FILES_GetMemoryMapping(
            MapFile,
            out size,
            MapName,
            out PacketSize,
            ref *nullMapping,    // wat?
            out PagePerSector);
}

看起来像它应该在运行时失败,但它没有,因为ref*相互抵消,结果值ref *nullMapping的空值是空指针,这是FILES_GetMemoryMapping()将为该参数接收的内容。

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

答案 5 :(得分:1)

现在可以使用C#语言7.2或更高版本允许为空。只需将ref替换为您的函数参数,就像这样...

void MyFunc(ref Object obj) { ... }

到...

void MyFunc(in Object obj) { ... }

这将使您在应用程序中调用函数时将null作为参数值传递。它在对象和本机类型上均相同,并且在语法上等效于ref readonly

答案 6 :(得分:0)

也许不是完全理想的答案,但是如果在调用函数时需要将null作为参数传递,请考虑对该函数进行重载,从而忽略要设置为null的变量的形式参数。

例如,假设您有一个看起来像这样的函数:

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

您希望能够为参数z传递null。尝试创建一个新的MyFunction重载,如下所示:

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

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