如何解决 CA2202:避免生成 System.ObjectDisposedException 警告 [重复]

Posted

技术标签:

【中文标题】如何解决 CA2202:避免生成 System.ObjectDisposedException 警告 [重复]【英文标题】:How To Solve CA2202:To avoid generating a System.ObjectDisposedException Warning [duplicate] 【发布时间】:2015-12-26 08:51:44 【问题描述】:

每次在 Visual Studio 2015 上运行 Code Analysis 时,都会出现一些烦人的警告。它们都在这样的方法中:

这是我的方法:

public static JObject ReadJson(string file_path)

    try 
        JObject o1 = JObject.Parse(File.ReadAllText(file_path));
        using (StreamReader file = File.OpenText(file_path))
        
            using (JsonTextReader reader = new JsonTextReader(file))
            
                return (JObject)JToken.ReadFrom(reader);//the warning is here
            
        
    
    catch
    
        return default(JObject);
    


那么为什么会出现这个警告呢?如何解决?最重要的是什么 这种方法是我的错,在我看来非常完美

警告说明

严重性代码描述项目文件行警告 CA2202: Microsoft.Usage :对象“文件”可以在中多次处理 方法'JsonHelper.ReadJson(string)'。为了避免产生 System.ObjectDisposedException 你不应该调用 Dispose 超过 一次在一个物体上。

【问题讨论】:

我正在使用using Newtonsoft.Json; using Newtonsoft.Json.Linq; 【参考方案1】:

MSDN:

嵌套 using 语句(在 Visual Basic 中使用)可能导致违规 CA2202 警告。如果嵌套内部的 IDisposable 资源 using 语句包含外部 using 语句的资源, 嵌套资源的 Dispose 方法释放所包含的 资源。当出现这种情况时,外部的 Dispose 方法 using 语句尝试第二次释放其资源。

问题:

using (StreamReader file = File.OpenText(file_path))

    using (JsonTextReader reader = new JsonTextReader(file))
    
        return (JObject)JToken.ReadFrom(reader);//the warning is here
       //"file" will be disposed here for first time when "reader" releases it
   //and here it will be disposed for the second time and will throw "ObjectDisposedException"

解决方案:

你需要这样做(当一切顺利时将对象放置在 finally 块中,或者在发生错误时将对象放置在 catch 块中):

public static JObject ReadJson(string file_path)
   
    StreamReader file = null;
    try 
        JObject o1 = JObject.Parse(File.ReadAllText(file_path));
        file = File.OpenText(file_path);
        using (JsonTextReader reader = new JsonTextReader(file))
        
            return (JObject)JToken.ReadFrom(reader);
        
    
    catch
    
        return default(JObject);
    
    //dispose "file" when exiting the method
    finally
    
        if(file != null)
            file.Dispose();
    

【讨论】:

我认为您需要从捕获中删除处置,否则您也会在这里双重处置...... @Clockwork-Muse 是的!谢谢指点。 这个答案错过了链接文档的关键部分。由于JsonTextReader 对象在底层StreamReader 上调用Dispose(),当它本身是Dispose()-ed 时它被传递,你不应该自己调用它。解决方案是将您对StreamReader 的引用重置为using (JsonTextReader...) 块内的null,这样您就不会在finally 中重新设置Dispose()。您发布的内容基本上是编译器在使用 using 时为您所做的扩展(尽管由于您共享现有的 try 块而略有不同),并且没有修复 CA 警告。

以上是关于如何解决 CA2202:避免生成 System.ObjectDisposedException 警告 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

处理具有 2 个流的对象

代码分析规则 CA2000 / CA2202

MemoryStream、XmlTextWriter 和警告 4 CA2202:Microsoft.Usage

异常过滤器触发 CA2202?

WPF代码分析:CA2202 Do not dispose objects multiple timesObject

空条件运算符和 CA2202:不要多次处理对象