C#:如何将 null 传递给需要引用的函数?
我有以下函数:
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
I'我尝试修复这个问题。
有什么建议么?
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.
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
无法传递
null
的原因是 C# 编译器对ref
参数进行了特殊处理。 任何 ref 参数都必须是可以传递给您正在调用的函数的引用。 由于您想要传递null
,编译器拒绝允许这样做,因为您没有提供函数期望的引用。您唯一真正的选择是创建一个局部变量,将其设置为 null,然后将其传入。编译器不允许您执行更多操作。
The reason you cannot pass
null
is because aref
parameter is given special treatment by the C# compiler. Anyref
parameter must be a reference that can be passed to the function you are calling. Since you want to passnull
the compiler is refusing to allow this since you are not providing a reference that the function is expecting to have.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.我假设映射是一个结构? 如果是这样,您可以拥有两个版本的具有不同签名的 FILES_GetMemoryMapping() 原型。 对于要传递
null
的第二个重载,使参数为IntPtr
并使用IntPtr.Zero
调用示例:
如果 Mapping 实际上是类而不是结构体,只需在传递之前将值设置为 null 即可。
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 passnull
, make the parameter anIntPtr
and useIntPtr.Zero
Call example:
If Mapping is actually a class instead of a structure, just set the value to null before passing it down.
一种方法是创建一个虚拟变量,将其分配为 null,然后将其传入。
One way is to create a dummy variable, assign it null, and pass that in.
虽然 @JaredPar 的答案无疑是正确答案,但还有另一个 > 答案:
不安全
代码和指针:看起来应该在运行时失败,但事实并非如此,因为
ref
和< code>* 相互抵消,ref *nullMapping
的结果值为空指针,这就是FILES_GetMemoryMapping()
将为该参数接收的内容。这可能不是一个好主意,但是有可能。
While @JaredPar's answer is undoubtedly the correct answer, there is another answer:
unsafe
code and pointers:That looks like it should fail at runtime, but it doesn't, because the
ref
and the*
cancel each other out, and the resulting value ofref *nullMapping
is the null pointer, which is whatFILES_GetMemoryMapping()
will receive for that parameter.This is probably not a good idea, but it's possible.
现在可以使用 C# 语言 7.2 或更高版本允许 Null。 只需将函数参数中的
ref
替换为...,
这样您就可以在应用程序中调用函数时传入
null
作为参数值。 它对于对象和本机类型的工作方式相同,并且在语法上等同于ref readonly
。Null can now be permitted using C# language 7.2 or greater. Simply replace the
ref
in your function parameter like so...to...
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 toref readonly
.您可以使用 System.Runtime.CompilerServices.Unsafe 类获取 null 引用。
You can get a null ref using
System.Runtime.CompilerServices.Unsafe
class.兄弟,然后像c中一样使用指针
bro, then use pointers like in c
也许这并不完全是理想的答案,但如果您在调用函数时需要传递 null 作为参数,请考虑对该函数进行重载,以省略您尝试设置为 null 的变量的形式参数。
例如,假设您有一个如下所示的函数:
您希望能够为参数 z 传递 null。 尝试创建一个新的
MyFunction
重载,如下所示:这种方法不能满足每个人的需求,但它是另一种可能的解决方案。
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.
For example, let's say you have a function that looks like this:
You want to be able to pass null for parameter z. Try instead creating a new
MyFunction
overload that looks something like this:This approach won't suit everyone's needs, but it's another possible solution.
System.Runtime.CompilerServices.Unsafe:
这不需要在项目中启用不安全代码。
System.Runtime.CompilerServices.Unsafe:
This doesn't require enabling unsafe code in the project.