From https://msdn.microsoft.com/en-us/library/bb297966(v=vs.110).aspx
[ComVisibleAttribute(false)]
public static T CompareExchange(
ref T locati
As the other answer says, it's perfectly OK to have your variable contain null
-- it's about the reference to the variable being null
, and that can't happen in C#, or most other managed languages for that matter.
That said, you can make Interlocked.CompareExchange
throw a NullReferenceException
by working directly from IL. But even there you have to get tricky if you want to remain in the realm of managed, verifiable code:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init ([0] int32& x) // x is initialized to null
ldloc.0
ldc.i4.1
ldc.i4.2
call int32 [mscorlib]System.Threading.Interlocked::CompareExchange(
int32&, int32, int32)
pop
ret
}
This code will pass verification, but it will throw a NullReferenceException
at runtime. The stack trace will not actually show Interlocked.CompareExchange
, since the JIT compiler inlines it to a single lock cmpxchg
instruction.
As @Sean correctly pointed out, this should not really justify the documentation saying that the method may throw a NullReferenceException
, because this technique can be used to break any function taking a ref
or out
parameter. For example, Int32.TryParse does not document that it can throw a NRE if "the address of result
is null
", nor would we expect it to. Managed code is implicitly expected to be well-behaved when it comes to references.
The documentation is misleading here, as location1
cannot be null
since in C# it must always reference an existing variable. So yes, it is ok as what you are saying is "set location1
(that currently contains null) to be src
if location1
is already null
".
In fact because location1
has to be a reference it is impossible to pass a null-reference in C#, although it it possible (and valid) to pass a reference to something that is null, and so this function will never throw a NullReferenceException
.
I suspect this is down to the documentation being ported over from the Win32 api, where you have to pass a pointer to the location to read/write the variable, and it would be an error to pass null
here.