“CA2000 在失去范围之前处理对象”,原因不明

Posted

技术标签:

【中文标题】“CA2000 在失去范围之前处理对象”,原因不明【英文标题】:"CA2000 Dispose objects before losing scope " for unknown reason 【发布时间】:2013-06-19 22:09:06 【问题描述】:

我查看了 MSDN 文档,并在此代码片段中采用了推荐的模式:

  BitmapSymbols temp = null;
  try 
    using (var source = bitmaps.Symbols) 
      temp = new BitmapSymbols(source, sizeSymbols);
    
    _bitmapSymbols = temp;
    temp           = null;
   finally  
    if (temp!=null) temp.Dispose(); 
  

有谁知道为什么在这种情况下会报告temp?我看不到任何未处理 temp 且未设置为“null”的执行路径。提前感谢您的任何帮助。

如果我在 using 中将分配从 temp 移动到另一处,则会从 FxCop 生成相同的警告。

BitmapSymbols 类实现了IDisposable,并且是多个位图集合的包装器,可确保它们都被同时释放。

更新: 问题提出如下:

无论如何,我不明白你为什么想出这段代码而不是简单地使用:_bitmapSymbols = new BitmapSymbols(source, sizeSymbols);

原因是如果发生异常,不遵循模式可能会导致内存泄漏。我正在编写一个游戏,用户可能会运行数小时或数天而无需重新启动,因此避免内存泄漏对于稳定性很重要。

【问题讨论】:

temp 是否实现IDisposable @DJKRAZE:是的,代码编译和运行都很好,所以temp 实现了IDisposabe;这只是 FxCop 的抱怨,但我在其他几个地方使用了相同的模式,并且在其中一些地方得到了相同的 FxCop 警告。 为什么要在 using.. 之外设置 temp = null? @DJKRAZE:没关系;我已经尝试了两种方法,并从 FxCop 中得到了相同的警告。你能看出为什么偏爱一个而不是另一个的原因吗?我不能。 如果你将 temp.Dispose 重写为 ((IDisposable)temp).Dispose(); 如果它在编译时抱怨,那么只需将 temp 的值设置为 null 并继续 【参考方案1】:

我终于偶然发现了误报的原因(两个不同的案例),即使 MSDN 文档 here 中推荐的模式CA2000 Dispose Objects Before Losing Scope 紧随其后:

    如果临时一次性变量的名称不是显示的确切模式,即在 camelCase 中附加到目标一次性变量的字符串“temp”,则会生成误报由于未能识别推荐的模式。更改名称很容易消除误报。

    如果目标一次性变量是属性而不是字段或局部变量,则无法识别该模式。消除此处的误报需要编写一个一次性函数,如下所示:

    void SomeMethod() 
      // :  
      HexgridPath   = SetGraphicsPath();
      // :
    
    
    GraphicsPath SetGraphicsPath() 
      GraphicsPath path     = null;
      GraphicsPath tempPath = null;
      try 
        tempPath  = new GraphicsPath();
        tempPath.AddLines(new Point[] 
          new Point(GridSize.Width*1/3,                0), 
          new Point(GridSize.Width*3/3,                0),
          new Point(GridSize.Width*4/3,GridSize.Height/2),
          new Point(GridSize.Width*3/3,GridSize.Height  ),
          new Point(GridSize.Width*1/3,GridSize.Height  ),
          new Point(                 0,GridSize.Height/2),
          new Point(GridSize.Width*1/3,                0)
         );
        path     = tempPath;
        tempPath = null;
       finally  if(tempPath!=null) tempPath.Dispose(); 
      return path;
    
    

第一种情况看起来像是典型的“初级程序员的第一次作业-刚毕业”的错误;

第二种情况可能更难解决,但很烦人。

希望遇到这些误报的其他人可以从该分析中受益。从长远来看,小的代码更改比简单地禁用错误要好,以防初级程序员“优化”补救措施。

【讨论】:

【参考方案2】:

我相信删除if (temp != null) 会使警告消失。 FxCop 不够聪明,无法检查我认为的条件执行路径。

无论如何,我不明白你为什么想出这段代码而不是简单地使用_bitmapSymbols = new BitmapSymbols(source, sizeSymbols);

【讨论】:

以上是关于“CA2000 在失去范围之前处理对象”,原因不明的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 存档工具 - 看似正常的错误,但原因不明

Cloud Bigtable 批量突变因不明原因而失败

“cURL 错误 77:设置证书验证位置时出错”,原因不明

wxPython脚本挂不明原因问题,怎么解决

大学关键应用不明原因崩溃怎么办?

大学关键应用不明原因崩溃怎么办?