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 { // 最后块总是运行 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(); } //即使我们更早返回,也会调用Dispose }
就像finally块总是执行而不管错误或返回如何,using总是调用Dispose(),即使发生错误也是如此:
int Foo() { var fileName = "file.txt"; using (var disposable = File.Open(fileName, FileMode.Open)) { throw new InvalidOperationException(); } //即使我们提前抛出异常也会调用Dispose }
注意:由于Dispose可以确保无论代码流如何都调用它,因此最好在实现时确保Dispose不引发异常IDisposable。否则,实际异常将被新异常覆盖,从而导致调试恶梦。
using ( var disposable = new DisposableItem() ) { return disposable.SomeProperty; }
由于try..finally该using块将其转换为语义,因此该return语句可以按预期工作-在finally执行块和处理该值之前先评估返回值。评估顺序如下:
评估try身体
评估并缓存返回的值
最后执行块
返回缓存的返回值
但是,您可能不会返回变量disposable本身,因为它将包含无效的,已处置的引用-请参见相关示例。