简体   繁体   中英

Is it necessary to nest usings with IDisposable objects?

Do I have to wrap all my IDisposable objects in using(){} statements, even if I'm just passing one to another? For example, in the following method:

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;
}

Could I consolidate this to just one using like this:

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

Can I count on both the Stream and the StreamReader being disposed? Or do I have to use two using statements?

Yes, you can , but that's because the StreamReader constructor documentation specifically says: "The StreamReader object calls Dispose on the provided Stream object when StreamReader.Dispose is called."

If it didn't, then you could do something like this to at least clean up the code a bit.

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

The person/code/layer that created the disposable object should in general be responsible for disposing the object. However there are scenarios you might have where this isn't the case and that is OK. It becomes an issue then of documentation.

I found this question wider than simple question of using statement nesting, this is a pretty interesting application design problem.

Do I have to wrap all my IDisposable objects in using(){} statements, even if I'm just passing one to another?

Yes, since you are instantiating object which implements IDisposable - you are aware of disposing it, either by wrapping in using() or explicit Dispose() call.

Reason behind this is simple, imagine next scenario: you have following entities

  • TransportService
  • ReportService
  • FeedService

all implements IDisposable . Both ReportService and FeedService requires instance of TransportService to be passed in whilst construction stage. And question - is it correct disposing TransportService in the Dispose() of either ReportService or FeedService? No! Becuause the same instance of transport service could be passed in both services and once one of the disposes transport - this will affect all services as well.

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();
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM