2012-03-30 45 views
11

我是否必须将所有IDisposable对象包含在using(){}声明中,即使我只是将一个对象传递给另一个对象?例如,在下面的方法:是否需要使用IDisposable对象进行嵌套?

public static string ReadResponse(HttpWebResponse response) 
{ 
    string resp = null; 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     using (StreamReader responseReader = new StreamReader(responseStream)) 
     { 
      resp = responseReader.ReadToEnd(); 
     } 
    } 
    return resp; 
} 

我能巩固这只是一个using这样的:

public static string ReadResponse(HttpWebResponse response) 
{ 
    string resp = null; 
    using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
    { 
     resp = reader.ReadToEnd(); 
    } 
    return resp; 
} 

我可以指望StreamStreamReader都被设置?或者我必须使用两个using声明?

回答

12

是的,你可以,但是那是因为StreamReader的构造文档特别说:“StreamReader对象调用Dispose时StreamReader.Dispose被称为提供的流对象”

如果没有,那么你可以做这样的事情,至少清理一下代码。

using (Stream responseStream = response.GetResponseStream()) 
using (StreamReader responseReader = new StreamReader(responseStream)) 
{ 
    resp = responseReader.ReadToEnd(); 
} 
+0

我喜欢堆叠使用,比大量缩进更清洁:-) – 2012-03-30 19:45:57

+0

想象大括号是可选的。他们与任何其他陈述如“if”陈述一样。它是写有效的代码“if(expression)if(expression2)if(expression3){/ *多行代码。* /}“,其中每个if语句嵌套在前一个语句中 – 2012-03-30 19:50:04

+0

@Moozhe编译它并不令人惊讶,它更像VS处理缩进的方式,当使用括号时,它会在额外的级别中选中它,这不是,如果做到这一点,我可能甚至不会使用它 – Servy 2012-03-30 20:02:14

2

我发现这个问题比using声明嵌套的简单的问题更广泛,这是一个非常有趣的应用程序设计问题。

我必须包装在使用(){}声明我所有的IDisposable的对象, 即使我只是路过一个到另一个?

是的,因为你是实例,它实现IDisposable对象 - ,无论是在using()或显式调用Dispose()包装大家都知道它配置的。这背后

原因很简单,设想在下一个场景:你有以下实体

  • TransportService
  • ReportService的
  • FeedService

所有工具IDisposableReportServiceFeedService都需要TransportService的实例在施工阶段进入。还有问题 - 在ReportService或FeedService的Dispose()中配置TransportService是否正确?没有!因为可以在两种服务中传递相同的传输服务实例,并且只要其中一个处理传输 - 这也会影响所有服务。

public sealed class ReportService : IDisposable 
{  
    private readonly ITransportService transportService; 

    public ReportService(ITransportService transportService) 
    { 
     this.transportService = transportService; 
    } 

    public Dispose() 
    { 
     // ReportService should not dispose objects 
     // passed in since they could be used by other classes as well 
     // DO NOT: transportService.Dispose(); 
    } 
} 
+1

这不是一个真正的“总是处置”或“从不处理”的问题,有两条路径;当你传递一个可丢弃的对象到另一个你不再负责处理它,并且无论他们通过它将确保它被丢弃。这就是发生在这里的事情,当你将一个流传递给流媒体播放器时,你说:“你处理这个流“,如果你给一个可抛弃的对象给别人,但说”我仍然负责处理这个,它的范围比你大“,那么你传递给它甚至不需要实现IDisposable。 – Servy 2012-03-30 20:15:26

+0

你会看到很多例子后者与DataContexts的关系。我可能有一个帮助方法/类,它接受一个DataContext的实例,甚至不是一次性的。它不会处理DataContext,它知道谁将它交给DataContext将负责清理它并确保它在我仍在使用时不会丢弃。 – Servy 2012-03-30 20:16:31

3

创建一次性对象的人员/代码/图层通常应负责处理对象。但是,有些情况下,您可能会遇到这种情况,但情况并非如此。它成为文档的一个问题。