理解using语句

时间:2015-04-10 09:43:54

标签: c# .net using-statement

我写了两个代码:

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

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

代码块1抛出错误:stream is not reachable
虽然在进步中,我认为两个代码将一样。
我在代码块2中添加了使用块到整个语句并且它正在工作。
但我很困惑为什么它在代码块1中抛出错误

6 个答案:

答案 0 :(得分:5)

根据您指定的行为,似乎在处置HttpWebResponse时,它会处理响应流。

答案 1 :(得分:2)

Rohit,第一个代码块抛出错误,因为一旦关闭using子句的大括号,该对象就被视为已丢弃。即,该对象留给GC收集。代码块1中的流的范围在第二个using语句之前已过期。

访问流的正确方法是第二个代码块。

答案 2 :(得分:1)

using块可让您轻松,正确地使用一次性物品。因此,即使您在using语句之外声明变量,using语句中初始化的任何内容都将在using块之后被处理。

from msdn

  

通常,当您使用IDisposable对象时,您应该声明和   在using语句中实例化它。 using语句调用   以正确的方式处理对象上的方法,以及(当您使用它时)   如前所示)它也会导致对象本身超出范围   只要调用Dispose。在使用块中,对象是   只读,无法修改或重新分配。

答案 3 :(得分:1)

Stream不是数据块,而是从“某处”读取数据的方法。 当您处理该响应时(通过退出使用块),您将断开与“某处”的连接。这意味着您无法再从该流中读取。

你的第二个例子让这个连接保持活着,直到你读完为止。

答案 4 :(得分:1)

using语句确保当执行到达最后一个括号}时,作用域对象在其上调用了Dispose函数,这意味着HttpWebResponse对象在第二个使用块中超出范围。 / p>

虽然您已在datastream变量中保存了流,但尚未读取流本身,并且在您调用ReadToEnd()时已完成此操作。由于HttpWebResponse超出范围或Disposed,您将收到您收到的异常。

答案 5 :(得分:0)

因为后编译(在IL中),您的代码将转换为以下

代码块: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();
            }

代码块: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();
            }

正如您所看到的,在CodeBlock1中,您正在尝试访问尝试从Disposed(和断开连接的)HttWebResponse对象读取的流。