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.