C#:如何将 null 传递给需要引用的函数?

发布于 2024-07-17 01:12:13 字数 551 浏览 9 评论 0原文

我有以下函数:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

夏雨凉 2024-07-24 01:12:13

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

您唯一真正的选择是创建一个局部变量,将其设置为 null,然后将其传入。编译器不允许您执行更多操作。

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.

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.

半仙 2024-07-24 01:12:13

我假设映射是一个结构? 如果是这样,您可以拥有两个版本的具有不同签名的 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 即可。

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

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.

[旋木] 2024-07-24 01:12:13

一种方法是创建一个虚拟变量,将其分配为 null,然后将其传入。

One way is to create a dummy variable, assign it null, and pass that in.

顾铮苏瑾 2024-07-24 01:12:13

虽然 @JaredPar 的答案无疑是正确答案,但还有另一个 > 答案:不安全代码和指针:

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

看起来应该在运行时失败,但事实并非如此,因为ref和< code>* 相互抵消,ref *nullMapping 的结果值为空指针,这就是 FILES_GetMemoryMapping() 将为该参数接收的内容。

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

While @JaredPar's answer is undoubtedly the correct answer, there is another answer: unsafe code and pointers:

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

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 of ref *nullMapping is the null pointer, which is what FILES_GetMemoryMapping() will receive for that parameter.

This is probably not a good idea, but it's possible.

听,心雨的声音 2024-07-24 01:12:13
Mapping oMapping = null;

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

FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, ref oMapping, out PagePerSector);
薄荷港 2024-07-24 01:12:13

现在可以使用 C# 语言 7.2 或更高版本允许 Null。 只需将函数参数中的 ref 替换为...

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

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

这样您就可以在应用程序中调用函数时传入 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...

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.

箹锭⒈辈孓 2024-07-24 01:12:13

您可以使用 System.Runtime.CompilerServices.Unsafe 类获取 null 引用。

ref Unsafe.AsRef<Mapping>(null)

You can get a null ref using System.Runtime.CompilerServices.Unsafe class.

ref Unsafe.AsRef<Mapping>(null)
最笨的告白 2024-07-24 01:12:13

兄弟,然后像c中一样使用指针

public static extern unsafe uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    Mapping* oMapping,
    out byte PagesPerSector);

// somewhere in code
unsafe {
    uint result = FILES_GetMemoryMapping("path", out ushort size, "map", out ushort packetSize, null, out byte pages);
}

bro, then use pointers like in c

public static extern unsafe uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    Mapping* oMapping,
    out byte PagesPerSector);

// somewhere in code
unsafe {
    uint result = FILES_GetMemoryMapping("path", out ushort size, "map", out ushort packetSize, null, out byte pages);
}

盛装女皇 2024-07-24 01:12:13

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

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

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

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

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

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

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:

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:

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

This approach won't suit everyone's needs, but it's another possible solution.

淡笑忘祈一世凡恋 2024-07-24 01:12:13

System.Runtime.CompilerServices.Unsafe:

ref Unsafe.NullRef<Mapping>()

这不需要在项目中启用不安全代码。

System.Runtime.CompilerServices.Unsafe:

ref Unsafe.NullRef<Mapping>()

This doesn't require enabling unsafe code in the project.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文