如何修复代码分析警告

问题描述:

我有一个代码如何修复代码分析警告

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

line 224指的是第13行在这之前的结尾括号return responce;

我该如何解决此警告。

MSDN

StreamReader对象所提供的流对象时 StreamReader.Dispose上调用调用Dispose()。

这意味着StreamReader将调用Stream对象上的Dispose,并且您的using语句也会这样做。选择可以是:

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

这两行引用相同的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(); 
} 

这里的更深层次的问题是,StreamReader设计是不正确;它不应该配置底层的流,因为它不会自己它。

下面的模式是很常见:

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

public class Bar: IDisposable { ... } 

处置时foo,它不应该自动为您处理bar,因为它并不拥有bar; bar是由foo的用户提供的对象;因此其用户负责照顾bar

这实际上是在你的代码中发生的事情;你正在照顾stream,但StreamReader也照顾一些不是真正的业务,也为你处置stream

因此,总结:你的代码是正确的。由于StreamReader中的设计缺陷,您的正确代码正在创建需要照顾的问题;重复拨打Dispose()

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