何时使用Using语句

4

我觉得我在这里使用了错误的Using语句。有没有更好的写法?

Dim x As New Serialization.XmlSerializer( ... )
Using file As New FileStream(myFile, FileMode.Create)
   Using writer As XmlWriter = XmlTextWriter.Create(file)
      x.Serialize(writer, myCollection)
   End Using
End Using

我读到过只有在对象具有.Dispose()(即实现IDisposable)时才应使用using块,这就是为什么我认为"writer"上不应该有Using,而应该在结尾处使用writer.Close()。但是"file"既具有.Dispose()又具有.Close(),那我应该使用哪个?是using还是file.Close()?
注意:我正在使用XmlWriter,因为我可以自定义输出。我在此处删除了设置。
5个回答

11

FileStreamXmlWriter都实现了IDisposable接口 - 该代码是正确的。事实上,如果有问题,编译器可能不会让你这样做。如果没有公共的.Dispose(),那么它必须使用显式接口实现 - 但这并不改变您调用.Dispose()的责任。有趣的是,在C#中,您可以避免嵌套/缩进不断增加,例如:

using(...a...)
using(...b...)
using(...c...)
{
   ...
}

但是从根本上讲,你目前的代码是正确的。


1
我建议在 Serialize() 之后添加 writer.Flush() 语句。如果不显式刷新它们,流编写器以不写入最后一批缓冲数据而出名。 - Toby
2
谢谢!但是 .Dispose() 不会调用 .Close()(就像 Hans Passant 说的那样),然后再调用 .Flush() 吗?所以使用 Using 就可以处理所有这些问题了吧? - grant
1
如果您感兴趣,也可以像这样在VB中避免过多的缩进:Using a As New blah, b As New blah链接 - MarkJ
@MarkJ 谢谢;我不会猜到那个语法。我的 VB.NET 主要 是只读的,也许有些丢脸。 - Marc Gravell
1
@Marc VB比C#更简洁的领域之一 ;) - MarkJ
显示剩余2条评论

3

这确实令人困惑,也引起了很多争议。Dispose()方法的实现如下:

Public Sub Dispose()
    Me.Close
End Sub

换句话说,调用Dispose()与调用Close()的作用完全相同。在这里,您肯定希望利用Using语句。

谢谢!所以基本上只要可能就使用“Using”(尤其是在处理流时)? - grant
1
如果您在另一个方法中打开文件并稍后关闭它,那么使用Close()是有意义的。这基本上就是它存在的原因。 - Hans Passant

2

是的,.Close .Dispose 问题有点不幸。

尽管如此,它仍然是(还是?)MS的一项官方指导方针。Close方法被称为一个特定领域的别名

就像别名这个词所暗示的那样,你可以认为它们完全相同。通常,Close只会调用Dispose。

Using ... End Using 块只会在引用IDisposable(具有.Dispose)的情况下编译。


一般建议:

  • 当类有.Dispose时,请使用Using
  • Using只是Try ... Finally的简写,您可以回退到此方式。但是
  • 不要尝试组合或节约多个块
  • 当嵌套深度过深(>3..5)时,请分离出额外的方法。

1

你的代码看起来是正确的。请注意,如果你尝试在不支持IDispose的数据类型上使用using,你将会得到一个编译时错误。


1

我倾向于两者都做,但这可能是因为我有点老派。如果我打开了一个文件(你已经打开了),我会明确地关闭它。Dispose方法是否进行干净的关闭取决于对象的实现,而不是客户端。但是,由于对象仍然实现了IDisposable,因此您仍然需要调用它。


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