为什么在C#中使用(null)有效的案例?

时间:2011-03-04 08:37:35

标签: c# .net using-statement

有人可以向我解释为什么下面显示的代码在C#中有效并执行对Console.WriteLine的调用吗?

using (null) 
{
   Console.WriteLine ("something is here")
}

编译成(最后显示块)。如您所见,编译器决定不执行Dispose()方法并跳转到endfinally指令。

IL_0013:  ldnull
IL_0014:  ceq
IL_0016:  stloc.1
IL_0017:  ldloc.1
IL_0018:  brtrue.s   IL_0021 // branches here and decide not to execute Dispose()
IL_001a:  ldnull
IL_001b:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
IL_0020:  nop
IL_0021:  endfinally

但是,如果我运行以下代码,它将失败并显示NullReferenceException(预期):

((IDisposable)null).Dispose();
IL_0023:  ldnull
IL_0024:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()

为什么第一个版本会编译?为什么编译器决定不执行Dispose()?当编译器决定不在Dispose()块中调用using时,是否还有其他情况?

3 个答案:

答案 0 :(得分:12)

语言规范明确指出(8.13)在必要时测试捕获的值是否为null,即finally本质上是(围绕非可空类型的警告)

if(tmp != null) tmp.Dispose();

我经常使用这个对我有利,对于可能为空的东西,但是当它们不是时:需要处理。实际上,这是一个有用的场景(手动枚举IEnumerable):

IEnumerable blah = ...; // note non-generic version
IEnumerator iter = blah.GetEnumerator();
using(iter as IDisposable)
{
    // loop
}

由于IEnumerator的非通用版本不一定是IDisposable,但如果是,则应予以处理。

答案 1 :(得分:1)

我认为这是using(some_expression)的更一般情况的自然结果,其中some_expression is allowed to evaluate to null

这需要一个特殊的规则来区分这种情况和更普遍的情况。

答案 2 :(得分:0)

如果Object为null,它将忽略 - http://msdn.microsoft.com/en-us/library/yh598w02.aspx