可以Interlocked.CompareExchange抛出NullReferenceException吗? [英] Can Interlocked.CompareExchange throw NullReferenceException?

查看:33
本文介绍了可以Interlocked.CompareExchange抛出NullReferenceException吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自 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 <的任何函数./code>或 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吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆