C#: How to pass null to a function expecting a ref?

Viewed 54807

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?

9 Answers

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.

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.

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

Mapping oMapping = null;

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

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.

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.

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

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

ref Unsafe.AsRef<Mapping>(null)
Related