0

I have a method that returns like this:

using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
    return reader.ReadToEnd();

Can I combine the three usings like this and have the same level of safety?

using (var reader = new StreamReader(request.GetResponse().GetResponseStream()))
    return reader.ReadToEnd();

Or since this is inside a privately scoped function, can I return safely without a using?

return new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();

The object that contains this method is not IDisposable. I'm guessing no to both my questions but I am curious on other viewpoints.

Jaguir
  • 3,620
  • 1
  • 19
  • 26
  • Note that StreamReader's Dispose will dispose the stream you give it at construction. So it's unnecessary for you to explicitly dispose or wrap in a using the stream object. http://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream – hatchet - done with SOverflow Nov 06 '13 at 18:15
  • Dont think this question should be closed as duplicate. The fact streamreader is used gives rise to a different answer. –  Nov 06 '13 at 19:18

2 Answers2

4

For the general case, you can't make this assumption. For your specific case, some consolidation is possible. In particular, disposing the StreamReader will also close the underlying stream, because the documentation for StreamReader.Close() makes this guarantee:

Closes the StreamReader object and the underlying stream

(Emphasis mine). Therefore, you can skip middle using block from your sample. However, the same guarantee is not made from the Stream to the HttpResponse object, meaning you still want to keep that. So you can do this:

using (var response = request.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
    return reader.ReadToEnd();

Additionally, there is one other situation where you can combine stacked using blocks into a single block. When all of the items managed by the using blocks are of the same type, you can separate each object with a comma. For example, opening one file for reading and processing the output to another file can be done like this:

using (var infile = new FileStream("infile"), outfile = new FileStream("outfile"))
{
    //...
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I did not know about the stacking. I think requiring them to be the same type limits it's usefulness, but it is still nice to know. – Jaguir Nov 06 '13 at 19:25
  • 1
    There are two reasons you might not want to skip that `using` statement: 1. [`new StreamReader(Stream)` can throw](http://msdn.microsoft.com/en-us/library/yhfzs7at.aspx) (if `stream` is `null` or does not support reading), potentially leaving the stream unclosed. 2. [Because Skeet says so](http://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream). – Tim S. Nov 06 '13 at 20:00
  • @TimS. He does, but he also admits it's a preference, not a hard rule. – Joel Coehoorn Nov 06 '13 at 20:03
2

In general, you need the separate statements to ensure that everything gets cleaned up properly:

using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
    return reader.ReadToEnd();

Otherwise, an error partway through might leave resources undisposed. E.g. if GetResponseStream() threw an exception in this code, you'd end up with an undisposed response:

using (var reader = new StreamReader(request.GetResponse().GetResponseStream()))
    return reader.ReadToEnd();
Tim S.
  • 55,448
  • 7
  • 96
  • 122