为什么 using(null) 在 C# 中是有效的情况?
有人可以向我解释为什么下面显示的代码在 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()
?是否存在其他情况下编译器可能决定不在 using
块中调用 Dispose()
?
Could someone please explain to me why the code shown below is valid in C# and executes the call to Console.WriteLine
?
using (null)
{
Console.WriteLine ("something is here")
}
It compiles into (finally block is shown). As you can see compiler decides not to execute the Dispose()
method and jumps to the endfinally
instruction.
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
However, if I run the following code, it will fail with a NullReferenceException
(which is expected):
((IDisposable)null).Dispose();
IL_0023: ldnull
IL_0024: callvirt instance void [mscorlib]System.IDisposable::Dispose()
Why does the first version compile? Why does the compiler decide not to execute Dispose()
? Are there any other cases when compiler may decide not to call Dispose()
in a using
block?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
语言规范明确指出(8.13),如有必要,捕获的值将被测试为空,即
finally
本质上是(对不可为空类型的警告)我经常使用它来发挥我的优势,因为可能为空,但如果不是:需要处置。事实上,这是一个有用的场景(手动枚举
IEnumerable
):因为
IEnumerator
的非泛型版本不一定是IDisposable
,但是当是的,应该处理掉。The language spec explicitly states (8.13) that the captured value is tested for null if necessary, i.e. the
finally
is essentially (with caveats around non-nullable types)I frequently use this to my advantage, for things that might be null, but when they aren't: need disposing. In fact, here's a useful scenario (manually enumerating
IEnumerable
):as the non-generic version of
IEnumerator
isn't necessarilyIDisposable
, but when it is, should be disposed.我认为这是
using(some_expression)
更一般情况的自然结果,其中some_expression
允许计算为null
。需要制定一项特殊规则来区分这种情况与更一般的情况。
I think it's a natural outcome of the more general case of
using(some_expression)
, wheresome_expression
is allowed to evaluate tonull
.It would have required a special rule to distinguish this case from the more general one.
如果对象为空,它将忽略 - http://msdn.microsoft.com/ en-us/library/yh598w02.aspx
It will ignore if the Object is null - http://msdn.microsoft.com/en-us/library/yh598w02.aspx