C#:如何将 null 传递给需要 ref 的函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/736474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#: How to pass null to a function expecting a ref?
提问by Nick
I've got the following 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);
Which I would like to call like this:
我想这样称呼:
FILES_GetMemoryMapping(MapFile, out size, MapName,
out PacketSize, null, out PagePerSector);
Unfortunately, I cannot pass null
in a field that requires type ref Mapping
and no cast I've tried fixes this.
不幸的是,我无法传入null
需要类型的字段,ref Mapping
并且我尝试过的没有强制转换来解决这个问题。
Any suggestions?
有什么建议?
采纳答案by JaredPar
I'm assuming that Mapping is a structure? If so you can have two versions of the FILES_GetMemoryMapping()
prototype with different signatures. For the second overload where you want to pass null
, make the parameter an IntPtr
and use IntPtr.Zero
我假设 Mapping 是一个结构?如果是这样,您可以拥有两个FILES_GetMemoryMapping()
具有不同签名的原型版本。对于要传递的第二个重载null
,将参数设为anIntPtr
并使用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);
Call example:
调用示例:
FILES_GetMemoryMapping(MapFile, out size, MapName,
out PacketSize, IntPtr.Zero, out PagePerSector);
If Mapping is actually a class instead of a structure, just set the value to null before passing it down.
如果 Mapping 实际上是一个类而不是一个结构,只需在传递它之前将值设置为 null。
回答by Erich Mirabal
One way is to create a dummy variable, assign it null, and pass that in.
一种方法是创建一个虚拟变量,将其赋值为 null,然后将其传入。
回答by Chris Doggett
Mapping oMapping = null;
FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, ref oMapping, out PagePerSector);
回答by Andrew Hare
The reason you cannot pass null
is because a ref
parameter is given special treatment by the C# compiler. Any ref
parameter must be a reference that can be passed to the function you are calling. Since you want to pass null
the compiler is refusing to allow this since you are not providing a reference that the function is expecting to have.
无法传递的原因null
是因为ref
C# 编译器对参数进行了特殊处理。任何ref
参数都必须是可以传递给您正在调用的函数的引用。由于您想通过null
编译器拒绝允许这样做,因为您没有提供函数期望的引用。
Your only real option would be to create a local variable, set it to null
, and pass that in. The compiler will not allow you to do much more than that.
您唯一真正的选择是创建一个局部变量,将其设置为null
,然后将其传入。编译器不允许您执行更多操作。
回答by jonp
While @JaredPar's answeris undoubtedly the correctanswer, there is anotheranswer: unsafe
code and pointers:
虽然@JaredPar 的答案无疑是正确的答案,但还有另一个答案:unsafe
代码和指针:
unsafe {
Mapping* nullMapping = null;
FILES_GetMemoryMapping(
MapFile,
out size,
MapName,
out PacketSize,
ref *nullMapping, // wat?
out PagePerSector);
}
That lookslike it should fail at runtime, but it doesn't, because the ref
and the *
cancel each other out, and the resulting value of ref *nullMapping
is the null pointer, which is what FILES_GetMemoryMapping()
will receive for that parameter.
这看起来像它应该在运行时失败,但它没有,因为ref
和*
相互抵消,所得的值ref *nullMapping
是空指针,这是FILES_GetMemoryMapping()
将收到该参数。
This is probably not a good idea, but it's possible.
这可能不是一个好主意,但它是可能的。
回答by Jazimov
Perhaps its not exactly the ideal answer, but if you need to pass null as a parameter when calling a function, consider making an overload of that function that omits the formal parameter for the variable you're trying to set to null.
也许它不完全是理想的答案,但是如果您需要在调用函数时将 null 作为参数传递,请考虑对该函数进行重载,忽略您尝试设置为 null 的变量的形式参数。
For example, let's say you have a function that looks like this:
例如,假设您有一个如下所示的函数:
public void MyFunction(string x, int y, ref string z) {...};
You want to be able to pass null for parameter z. Try instead creating a new MyFunction
overload that looks something like this:
您希望能够为参数 z 传递 null。尝试创建一个MyFunction
看起来像这样的新重载:
public void MyFunction(string x, int y) {...};
This approach won't suit everyone's needs, but it's another possible solution.
这种方法不能满足每个人的需求,但它是另一种可能的解决方案。
回答by Jim Fell
Null can now be permitted using C# language 7.2 or greater. Simply replace the ref
in your function parameter like so...
现在可以使用 C# 语言 7.2 或更高版本允许空值。只需ref
像这样替换函数参数中的...
void MyFunc(ref Object obj) { ... }
to...
到...
void MyFunc(in Object obj) { ... }
This will let you pass in null
as a parameter value when calling the function in your application. It works the same for objects and native types and is syntactically equivalent to ref readonly
.
这将允许您null
在应用程序中调用函数时作为参数值传入。它对对象和本机类型的工作方式相同,并且在语法上等同于ref readonly
.