【问题标题】:how to fix Code Analysis warnings [duplicate]如何修复代码分析警告[重复]
【发布时间】:2016-08-23 07:26:25
【问题描述】:

我有代码

public String makeHttpGetRequest(String url)
        {
            try
            {
                string responce = string.Empty;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.AutomaticDecompression = DecompressionMethods.GZip;


                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                using (Stream stream = response.GetResponseStream())
                using (StreamReader reader = new StreamReader(stream))
                {
                    responce = reader.ReadToEnd();
                }
                return responce;
            }
            catch (Exception e)
            {
                Console.WriteLine("Internet Connection error" + e.Message);
                return null;
            }
        }

当我在 Visual Studio 中运行代码分析时,我收到一条警告

CA2202 不要多次释放对象 对象“流”可以在方法“InformationIO.makeHttpGetRequest(string)”中多次释放。为避免生成 System.ObjectDisposedException,您不应在一个对象上多次调用 Dispose。: Lines: 244 InformationIO.cs 244

第 224 行是指第 13 行,这里是 return response;

之前的右括号

我该如何解决这个警告。

【问题讨论】:

    标签: c# code-analysis


    【解决方案1】:

    这两行引用了相同的stream,并会尝试两次释放它:

    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream))
    

    删除第二个 using 块(您拥有的三个块中的),因为在这种情况下它是不必要的。

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        Stream stream = response.GetResponseStream());
        using (StreamReader reader = new StreamReader(stream))
        {
            responce = reader.ReadToEnd();
        }
    }
    

    如果您想真的确定流已被释放,请添加finally 块:

    Stream stream = null;
    try
    {
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            stream = response.GetResponseStream());
            using (StreamReader reader = new StreamReader(stream))
            {
                responce = reader.ReadToEnd();
            }
        }
    }
    finally
    {
        // check if stream is not null (although it should be), and dispose of it
        if (stream != null)
            stream.Dispose();
    }
    

    【讨论】:

      【解决方案2】:

      来自MSDN

      StreamReader 对象在提供的 Stream 对象上调用 Dispose() 当 StreamReader.Dispose 被调用时。

      这意味着 StreamReader 将在 Stream 对象上调用 Dispose 并且您的 using 语句也会这样做。替代方案可能是:

      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
          using (StreamReader reader = new StreamReader(response.GetResponseStream()))
          {
             responce = reader.ReadToEnd();
          }
      return responce;
      

      【讨论】:

        【解决方案3】:

        这里更深层次的问题是StreamReader的设计不正确;它不应该释放底层流,因为它不拥有它。

        以下模式很常见:

        public class Foo: IDisposable
        {
            public Foo(Bar bar) {...}
        }
        
        public class Bar: IDisposable { ... }
        

        在处理foo时,它不应该自动为你处理bar,因为它不拥有barbarfoo 的用户提供的对象;因此,用户有责任照顾bar

        这基本上就是您的代码中发生的事情;您正确地处理了stream,但StreamReader 也在处理与其业务无关的事情,也为您处理stream

        所以,总结一下:您的代码是正确的。由于StreamReader 中的设计缺陷,您的正确代码正在产生需要注意的问题;重复调用Dispose()

        其他答案指出了解决问题的好方法,所以我不会在这里重复代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-05-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多