在C#中,声明使用语句的目标对象应该在语句外部进行。

3
问题: 在使用语句中将目标对象声明为 'Code snippet 1' 中所示,是否有优势?

'Code snippet 2' 和 'Code snippet 3' 片段在我看来也是有效的,但不确定第一个代码片段是否比其他两个具有更多的优势。

代码片段 1

 using (TextWriter w = File.CreateText("log.txt")) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }

代码片段 2

 TextWrite w = null;
 using (w = File.CreateText("log.txt")) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }

代码片段 3

 TextWriter w = File.CreateText("log.txt");
 using (w) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }

更新1:看起来“代码片段3”可能会导致在实例化TextWriter对象时第一行发生异常时资源没有被处理。因此,前两个代码片段在资源处理方面是等价的,而第三个代码片段绝对不建议使用,除非第三个代码片段有一个finally块,在该块中处理TextWriter对象的处理。

更新2:在得到Peter的答案后,我意识到我在更新1中的观察结果是不正确的。解释如下:如果在任何3个代码片段中的任何一个中实例化TextWriter时出现异常,则Dispose方法将永远不会被调用,因为没有TextWriter对象可以调用此方法。


1
这取决于您是否想在 using 块的范围之外访问 w - Mike Christensen
主要的是编译器会在你尝试访问已经被处理掉的变量w时警告你,这很好。 - Tony Hopkinson
2个回答

3

您的示例#2和#3是等价的,与您在“UPDATE 1”中的假设相反。如果在File.CreateText()方法调用中发生异常,则不会返回任何对象并将其分配给w。因此,无论您是在using语句之前还是作为其一部分进行赋值,如果对象成功创建,则将根据需要成功清理。

话虽如此,示例#1至少有两个好处:

  1. 正如其他答案中提到的那样,它减少了变量的范围,使其仅在using语句块内可访问。这对于任何情况下都有用的原因是限定变量的范围。
  2. 另一个好处(在我看来也是最重要的好处之一)是,作为using语句的一部分声明的变量是只读的。这确保您不会意外编写尝试在可以清理之前切换可处理对象的代码,即创建只有一个可处理对象由using语句清理的模棱两可的情况。

你对我错过的那个微妙点是正确的。如果TextWriter没有被实例化,它就不会被处理,因为Dispose方法总是在创建的对象上调用。我们无法在空对象上调用Dispose。 - Sunil

2
唯一的潜在好处是减少了声明变量的可见性(因为它只在using块中可见),以及更好的可读性。

...并且在 using 块结束后,对象不会再次被意外地释放。 - helb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接