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

时间:2013-12-20 12:18:44

标签: c# try-catch dispose using streamwriter

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

StreamWriter writer;
try {
    writer = new StreamWriter(...)
    writer.blahblah();

} finally {
    writer.Dispose();
}

VS

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

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

6 个答案:

答案 0 :(得分:9)

您的代码存在一些问题从不这样写(改为使用),这就是的原因:

StreamWriter writer;
try {
    // What if you failed here to create StreamWriter? 
    // E.g. 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();
}

答案 1 :(得分:7)

  

这两个代码示例之间是否存在差异

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

  

为什么使用存在?

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

答案 2 :(得分:6)

你所写的几乎是using包含的模式。因此,每次使用Disposable对象时,using都需要保存必须写入相同try....finally块。

关于您编辑过的问题

  

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

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

所以你最终会得到这个:

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

答案 3 :(得分:1)

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

第二个区别在于代码可读性 - 请查看您的示例。第一个版本需要7行。第二个 - 只有3个。

答案 4 :(得分:1)

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

我建议使用using,因为不太可能犯错误。

答案 5 :(得分:1)

它们并不完全相同。 try / finally阻止不能防止愚蠢的错误。

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

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

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

会产生编译时错误。