编译器是否能够将以下任何代码合并到单个try/catch中?
using (FileStream stream = new FileStream(filePath, FileMode.Open))
{
using (BinaryReader reader = new BinaryReader(stream))
{
a try/catch around my actual code...
}
}
如果没有,如果我改为这样做,会有什么功能上的区别吗?
FileStream stream = null;
BinaryReader reader = null;
try
{
stream = new FileStream(filePath, FileMode.Open);
reader = new BinaryReader(stream)
// do my stuff
}
catch (stuff)
{
}
finally
{
if (stream != null)
stream.Close();
if (reader != null)
reader.Close();
}
由于拥有一个额外的try
/finally
的开销实际上为零,因此编译器将两个块合并为一个或将它们分开是没有区别的。翻译后的代码将在try
-finally
的两层中嵌入一个try
-catch
,这两层在性能方面几乎是免费的。
手动转换using
代码有不同的含义——变量的可见性不同。嵌套using
语句的转换使stream
和reader
变量在块之后可以访问。它们指的是封闭的流和封闭的读者。另一方面,正则using
将其变量保持在的范围内,就好像在整个块周围放置了一对额外的花括号:
{ // <<==
FileStream stream = null;
BinaryReader reader = null;
try {
stream = new FileStream(filePath, FileMode.Open);
reader = new BinaryReader(stream)
// do my stuff
} finally {
if (stream != null)
stream.Close();
if (reader != null)
reader.Close();
}
} // <<==
using
在这种方式下更好,因为它可以避免额外级别的嵌套,同时将其变量保持在本地范围内。此外,您可以通过将两个连续的using
块放在同一缩进级别,不使用大括号来降低源代码中的嵌套级别:
using (FileStream stream = new FileStream(filePath, FileMode.Open))
using (BinaryReader reader = new BinaryReader(stream)) {
a try/catch around my actual code...
}
编译器是否能够将以下任何代码合并为一个try/catch?
不,编译器无法使代码的行为与您编写的代码不同。即使没有Close()
和Dispose()
产生不同影响的可能性,情况也会有所不同,但让我们假设你自己打过Dispose()
。
如果没有,如果我改为这样做,会有什么功能上的区别吗?
是的。将两个Dispose()
调用放在一个finally
块中意味着,如果stream.Dispose()
抛出异常,则不会释放reader
。
没有编写良好的IDisposable
的Dispose()
方法抛出异常,但编译器不能知道或假设所有实现都编写良好。