【发布时间】:2009-06-03 20:23:00
【问题描述】:
我已经运行 ildasm 发现这个:
using(Simple simp = new Simple())
{
Console.WriteLine("here");
}
生成与此等效的 IL 代码:
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
if(simp != null)
{
simp.Dispose();
}
}
问题是为什么它会在 finally 中检查 null ? finally 块只有在 try 块被执行时才会被执行,而 try 块只有在 Simple 构造函数成功(即不抛出异常)时才会被执行,在这种情况下 simp 将是非空的。 (如果担心在 Simple 构造函数和 try 块的开头之间可能会出现一些干预步骤,那么这确实是一个问题,因为可能会引发异常,从而阻止 finally 块的执行。)那么,到底为什么?
抛开 using 语句是否比 try-finally 更好的论点,我将 try-finally 块写为:
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
simp.Dispose();
simp = null; // sanity-check in case I touch simp again
// because I don't rely on all classes
// necessarily throwing
// ObjectDisposedException
}
【问题讨论】:
-
我对一件事感到好奇:就性能而言,与编译器生成的健全性检查相比,额外的健全性检查(simp = null)有多“昂贵”?最后,这两者之间的区别似乎更具哲学性而不是实际性,但我可能弄错了。无论哪种方式都很有趣。
-
@Fredrik - 所以你问的是“设置为空”是否比“比较空”更快/慢?我不知道。除此之外,using 语句的一个好处是您不必担心该对象在 using 范围之外被访问。 (除非你持有另一个对它的引用。)
-
"为什么它会在 finally 中检查 null?"没有很好的理由。跳过空值检查是我们可以执行的优化。我们没有。没什么大不了的;空检查既短又便宜。
-
顺便说一句,如果一个表达式已知是非空的,因为它是新表达式的结果,C# 编译器会在许多地方执行类似这样的微优化。这只是我们错过的一个。
-
我在这里简单讨论一下这个优化:blogs.msdn.com/ericlippert/archive/2009/06/11/…
标签: c# using finally expansion try-catch