rohit singh
rohit singh

Reputation: 590

Understanding the using statement

I have written two codes:

code block 1:

Stream dataStream;
using (var response = (HttpWebResponse)req.GetResponse())
{
    dataStream = response.GetResponseStream();
}

//Open the stream using a StreamReader for easy access
using (var reader = new StreamReader(dataStream))
{
    data = reader.ReadToEnd();
}

code block 2:

Stream dataStream;
using (var response = (HttpWebResponse)req.GetResponse())
{
    dataStream = response.GetResponseStream();

    //Open the stream using a StreamReader for easy access
    using (var reader = new StreamReader(dataStream))
    {
        data = reader.ReadToEnd();
    }
}

Code block 1 is throwing error: stream is not reachable.
While progmatically i think both code will work same.
I added using block in to whole statment in code block 2 and it's working.
But I'm confused why is it throwing error in code block 1

Upvotes: 1

Views: 352

Answers (6)

Manish Basantani
Manish Basantani

Reputation: 17509

Because post compilation (in IL), your code gets converted to the following

Code Block: 1

            HttpWebResponse response=null;
            Stream dataStream;
            try
            {
                response = (HttpWebResponse) req.GetResponse();
                dataStream = response.GetResponseStream();
            }
            finally
            {
                if(response!=null)
                    ((IDisposable)response).Dispose();
            }

            StreamReader reader = null;
            try
            {
                //DataStream is accessed AFTER response object is disposed 
                reader = new StreamReader(dataStream);
                data = reader.ReadToEnd();
            }
            finally
            {
                if(reader!=null)
                    reader.Dispose();
            }

Code Block: 2

  HttpWebResponse response=null;
            Stream dataStream;
            try
            {
                response = (HttpWebResponse) req.GetResponse();
                dataStream = response.GetResponseStream();

                StreamReader reader = null;
                try
                {
                    //DataStream is accessed while response object is alive, and connected (not disposed)
                    reader = new StreamReader(dataStream);
                    data = reader.ReadToEnd();
                }
                finally
                {
                    if (reader != null)
                        reader.Dispose();
                }
            }
            finally
            {
                if(response!=null)
                    ((IDisposable)response).Dispose();
            }

As you can see, in CodeBlock1, you are trying to access stream which is trying to read from a Disposed (and dis-connected) HttWebResponse object.

Upvotes: 0

Naeem Sarfraz
Naeem Sarfraz

Reputation: 7430

The using statement ensures that the scoped object has the Dispose function called on it when the execution reaches the final bracket } which means the HttpWebResponse object is out of scope in the second using block.

Although you have saved your stream in the datastream variable the stream itself has not been read and that is done when you call ReadToEnd(). And as the HttpWebResponse is out of scope or Disposed then you are getting the exception you received.

Upvotes: 1

Hans Kesting
Hans Kesting

Reputation: 39348

A Stream is not a block of data, but a way to read that data from "somewhere". When you dispose of that response (by exiting the using-block) you break the connection to that "somewhere". This means you can't read from that stream anymore.

Your second example keeps that connection alive until you are done reading it.

Upvotes: 1

Zohar Peled
Zohar Peled

Reputation: 82534

the using block provides you easy and correct use of objects that are disposable. therefor, anything that is initialized in the using statement will be constidered as disposed after the using block, even if you declare the variable outside of the using statement.

from msdn:

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

Upvotes: 1

Siva Senthil
Siva Senthil

Reputation: 610

Rohit, the first code block is throwing error because, once you close the braces for the using clause, the object is considered as disposed. i.e. the object is left for the GC to collect. The scope of the stream in code block 1 had expired before the second using statement.

The right way to access the stream is the second code block.

Upvotes: 2

Trevor Pilley
Trevor Pilley

Reputation: 16423

Based upon the behavior you have specified, it would seem that when the HttpWebResponse is disposed, it disposes of the response stream.

Upvotes: 5

Related Questions