Reputation: 2959
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?
Upvotes: 55
Views: 63905
Reputation: 11
System.Runtime.CompilerServices.Unsafe:
ref Unsafe.NullRef<Mapping>()
This doesn't require enabling unsafe code in the project.
Upvotes: 0
Reputation: 39
You can get a null ref using System.Runtime.CompilerServices.Unsafe
class.
ref Unsafe.AsRef<Mapping>(null)
Upvotes: 3
Reputation: 308
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);
}
Upvotes: 1
Reputation: 14256
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
.
Upvotes: 3
Reputation: 13292
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.
Upvotes: 0
Reputation: 13600
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.
Upvotes: 5
Reputation: 754705
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.
Upvotes: 34
Reputation: 351516
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.
Upvotes: 51
Reputation: 20757
Mapping oMapping = null;
FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, ref oMapping, out PagePerSector);
Upvotes: 4
Reputation: 10038
One way is to create a dummy variable, assign it null, and pass that in.
Upvotes: 11