Interlocked.CompareExchange 可以抛出 NullReferenceException 吗?

Zan*_*ier 5 .net c#

来自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
Run Code Online (Sandbox Code Playgroud)

[ComVisibleAttribute(false)]
public static T CompareExchange<T>(
    ref T location1,
    T value,
    T comparand
)
where T : class
Run Code Online (Sandbox Code Playgroud)

但是当我对 使用空引用时location1,我没有收到任何错误:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做可以吗?这是否会NullReferenceException在 .NET 的更高版本中引发危险?

Jer*_*ert 1

正如另一个答案所说,让你的变量包含是完全可以的null——它是关于变量的引用null而这在 C# 或大多数其他托管语言中是不可能发生的。

也就是说,您可以通过直接从 IL 工作来生成Interlocked.CompareExchangethrow a NullReferenceException。但即便如此,如果您想留在托管的、可验证的代码领域,您也必须变得棘手:

  .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
  }
Run Code Online (Sandbox Code Playgroud)

这段代码将通过验证,但在运行时会抛出异常NullReferenceException。堆栈跟踪实际上不会显示Interlocked.CompareExchange,因为 JIT 编译器将其内联到单个lock cmpxchg指令。

正如 @Sean 正确指出的那样,这并不能真正证明文档中说该方法可能会抛出 a 的合理性NullReferenceException,因为这种技术可用于破坏任何采用 arefout参数的函数。例如,Int32.TryParse没有记录如果“地址是”它可以抛出 NRE resultnull我们也不希望它这样做。当涉及到引用时,托管代码隐含地期望表现良好。