.NET – 使用单个using语句替换嵌套的using语句

如果您使用嵌套的using语句/资源遇到了一些这样的C#代码:

using (var response = (HttpWebResponse)request.GetResponse()) { using (var responseStream = response.GetResponseStream()) { using (var reader = new BinaryReader(responseStream)) { // do something with reader } } } 

用这样的东西替换它是否安全?

 using (var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream())) { // do something with reader } 

上面的例子只是嵌套的一次性资源的一个例子,所以请原谅我,如果它不是完全正确的用法。 我很好奇当你处理最外层的资源(在这种情况下是BinaryReader),它是否会为你递归地处理它的子节点,或者你是否需要用单独的using语句显式地处理每个“层”? 例如,如果你处理BinaryReader,它是否应该处理响应流,而响应流又处理响应? 考虑到最后一句话让我觉得你确实需要单独的using语句,因为没有办法保证包装器对象会处理内部对象。 是对的吗?

您需要单独的using语句。

在第二个示例中,只会处理BinaryReader ,而不是用于构造它的对象。

为了了解原因,请查看using语句实际执行的操作。 它需要你的第二个代码,并做一些相当于:

 { var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream()); try { // do something with reader } finally { if (reader != null) ((IDisposable)reader).Dispose(); } } 

如您所见,在ResponseResponseStream上永远不会有Dispose()调用。

您应该只堆叠您的using语句 – 它具有您正在寻找的所需效果:

 using (var response = (HttpWebResponse)request.GetResponse()) using (var responseStream = response.GetResponseStream()) using (var reader = new BinaryReader(responseStream)) { // do something with reader } 

FWIW,这是拼写原始示例的另一种方式,可以满足任何对嵌套的沮丧:

 using (var response = (HttpWebResponse)request.GetResponse()) using (var responseStream = response.GetResponseStream()) using (var reader = new BinaryReader(responseStream)) { // do something with reader } 

读者是否处理流实际上是读者的function,而不是“使用”。 我记得通常是读者的行为 – 他们取得了流的所有权,并在读者自己关闭时处理它。 但我上面提供的表格应该没问题。

根据文档, BinaryReader.Close将关闭底层流。 http://msdn.microsoft.com/en-us/library/system.io.binaryreader.close.aspx

此外,根据HttpWebResponse的文档,您必须关闭基础流或处置响应。 http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx

所以你提供的第二个例子可行。

我在其他地方发布了这个,但是用逗号分隔你的声明似乎将每个语句以这种方式分隔为一个新的声明并处理它们。

using (IType1 a = new Type1(), b = new Type1()){}

但是,这意味着您的对象必须属于同一类型。 你可以称他们为

using (IDisposable a = new Type1(), b = new Type2()){}

但是当然,你只能访问IDisposable方法,而不会抛出对象,这有点愚蠢。 所以相反,我相信你可以使用

using (var a = new Type1(), b = new Type2()){}

这似乎为您提供了正确类型化的对象引用,允许您访问已分配类型的正确方法,并处置创建的两个对象。 如果有人知道我为什么不对,请告诉我,因为这对我有用吗? (我知道这个问题真的很老了,但我自己在搜索这个答案时就能找到它)