尝试/最后阻止vs调用dispose?

这两个代码示例之间是否有任何区别,如果没有,为什么using存在?

 StreamWriter writer; try { writer = new StreamWriter(...) writer.blahblah(); } finally { writer.Dispose(); } 

VS:

 using (Streamwriter writer = new Streamwriter(...)) { writer.blahblah } 

我的意思是在第二个例子中你真的应该把它放在try块中,所以添加finally块确实不会花费太多精力。 我知道整个事情可能包含在一个更大的尝试块中但是,对我来说似乎是多余的。

您的代码存在一些问题永远不要写这样(改为使用 ), 这就是为什么

 StreamWriter writer; try { // What if you failed here to create StreamWriter? // Eg you haven't got permissions, the path is wrong etc. // In this case "writer" will point to trash and // The "finally" section will be executed writer = new StreamWriter(...) writer.blahblah(); } finally { // If you failed to execute the StreamWriter's constructor // "writer" points to trash and you'll probably crash with Access Violation // Moreover, this Access Violation will be an unstable error! writer.Dispose(); } 

当你像那样“使用”时

  using (StreamWriter writer = new StreamWriter(...)) { writer.blahblah(); } 

它等于代码

 StreamWriter writer = null; // <- pay attention to the assignment try { writer = new StreamWriter(...) writer.blahblah(); } finally { if (!Object.ReferenceEquals(null, writer)) // <- ... And to the check writer.Dispose(); } 

这两个代码示例之间是否有任何区别

是的,在调用Dispose之前using null检查(即实际代码扩展为引入空检查)。

为什么使用存在?

因为代码更简洁。 只是一个语法糖。

你写的几乎就是using包装的模式。 因此,这是using节省必须编写相同的try....finally阻止每次使用Disposable对象。

至于你编辑过的问题

[…]在第二个例子中你真的应该把它放在try块中,所以添加finally块确实不会花费太多精力

您可能无法(或者不想)明确地处理来自blahblah错误,您只是想让它冒泡到调用代码……但仍然在清理StreamWriter资源的过程中!

所以你最终得到这个:

 StreamWriter writer; try{ writer = new StreamWriter(...) writer.blahblah(); }catch{ throw; // pointless! } finally [ writer.Dispose(); } 

后者只是前者的语法糖。 他们应该做同样的事情,但后者需要更少的样板代码。

我建议使用一个一个不太可能犯错误。

他们并不完全一样。 try / finally块不能防止愚蠢的错误。

 StreamWriter writer = new StreamWriter(...); try { ... writer = new StreamWriter(...); ... } finally { writer.Dispose(); } 

请注意,只有第二个作者被处置。 相反,

 using (StreamWriter writer = new StreamWriter(...)) { ... writer = new StreamWriter(...); ... } 

将给出编译时错误。

首先, 使用using比代码更安全 – 它可以正确处理Disposable对象构造中的错误,并且不会在null对象上调用dispose。

第二个区别在于代码可读性 – 看看你的例子。 第一个版本需要7行。 第二个 – 只有3个。