问题描述
来自 https://msdn.microsoft.com/en-us/library/bb297966(v = vs.110).aspx
[ComVisibleAttribute(false)]
public static T CompareExchange<T>(
ref T location1,
T value,
T comparand
)
where T : class
和
NullReferenceException The address of location1 is a null pointer.
但是当我对 location1
使用空引用时,不会出现任何错误:
But when I use a null reference for location1
, I don't get any errors:
class A { }
class Program
{
static void Main(string[] args)
{
A dest = null;
A src = new A();
// If dest is null, then replace with src.
Interlocked.CompareExchange(ref dest, src, null);
}
}
可以这样做吗?是否存在在更高版本的.NET中抛出 NullReferenceException
的危险?
Is it ok to do this? Is there a danger that this will throw NullReferenceException
in later versions of .NET?
推荐答案
正如另一个答案所说,让您的变量包含 null
是完全可以的-关于对变量为 null
,并且在C#或其他大多数托管语言中都不会发生这种情况.
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.
也就是说,您可以直接在IL上进行操作,使 Interlocked.CompareExchange
抛出 NullReferenceException
.但是,即使要保留在托管的可验证代码领域中,您也必须变得棘手:
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
}
此代码将通过验证,但会在运行时引发 NullReferenceException
.堆栈跟踪实际上不会显示 Interlocked.CompareExchange
,因为JIT编译器将其内联到单个 lock cmpxchg
指令中.
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.
正如@Sean正确指出的那样,这不应真正说明说该方法可能抛出 NullReferenceException
的文档是正当的,因为该技术可用于破坏使用 ref 或
out
参数.例如, Int32.TryParse
并没有说明它可以抛出如果"结果
的地址为 null
",则返回NRE,我们也不希望这样.隐式地期望托管代码在引用方面表现良好.
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.
这篇关于可以Interlocked.CompareExchange抛出NullReferenceException吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!