使用语句基础
using
是一个语法糖,可以保证资源被清理而不需要明确的 try-finally
块。这意味着你的代码将更加清晰,并且你不会泄漏非托管资源。
标准的 Dispose
清理模式,用于实现 IDisposable
接口的对象(FileStream
的基类 Stream
在 .NET 中执行):
int Foo()
{
var fileName = "file.txt";
{
FileStream disposable = null;
try
{
disposable = File.Open(fileName, FileMode.Open);
return disposable.ReadByte();
}
finally
{
// finally blocks are always run
if (disposable != null) disposable.Dispose();
}
}
}
using
通过隐藏显式 try-finally
简化了语法:
int Foo()
{
var fileName = "file.txt";
using (var disposable = File.Open(fileName, FileMode.Open))
{
return disposable.ReadByte();
}
// disposable.Dispose is called even if we return earlier
}
就像 finally
块总是执行而不管错误或返回,using
总是调用 Dispose()
,即使出现错误:
int Foo()
{
var fileName = "file.txt";
using (var disposable = File.Open(fileName, FileMode.Open))
{
throw new InvalidOperationException();
}
// disposable.Dispose is called even if we throw an exception earlier
}
注意: 由于无论代码流如何都保证调用 Dispose
,因此确保 Dispose
在实现 IDisposable
时不会抛出异常是个好主意。否则,新异常将覆盖实际异常,从而导致调试噩梦。
从使用块返回
using ( var disposable = new DisposableItem() )
{
return disposable.SomeProperty;
}
由于 using
块翻译的 try..finally
的语义,return
语句按预期工作 - 在执行 finally
块之前评估返回值并处理该值。评估顺序如下:
- 评估
try
的身体 - 评估并缓存返回的值
- 执行 finally 块
- 返回缓存的返回值
但是,你可能不会返回变量 disposable
本身,因为它将包含无效的,已丢弃的引用 - 请参阅相关示例 。