繁体   English   中英

CA2000:Microsoft.Reliability:在对所有引用超出范围之前调用System.IDisposable.Dispose对象'dt'

[英]CA2000 : Microsoft.Reliability : Call System.IDisposable.Dispose on object 'dt' before all references to it are out of scope

当我运行代码分析工具时,我得到以下内容:

警告1 CA2000:Microsoft.Reliability:在方法“Class1.test.testMethod()”中,对象“dt”未沿所有异常路径放置。 对所有对它的引用超出范围之前,在对象'dt'上调用System.IDisposable.Dispose。 如何解决警告?

public void testMethod()
{
   DataTable dt = new DataTable();
   DataTable dt1= new DataTable();
      try
      {
         if (dt.Rows.Count == 0)
         {
            dt1.Merge(dt);
         }
      }
      catch
      {
         throw;
      }
      finally
      {
         if (dt != null) dt.Dispose();
         if (dt1 != null) dt1.Dispose();
      }
}

不确定为什么会出现该错误,但您可以尝试在方法中using语句块并查看错误是否消失。 试试吧:

public void testMethod()
{
    using (DataTable dt = new DataTable())
    using (DataView dv = new DataView(dt))
    {
        //your work
    }
}

在丢失范围之前Dispose对象

如果在对所有对象的所有引用都超出范围之前没有明确地处置一次性对象,则当垃圾收集器运行对象的终结器时,该对象将在某个不确定的时间处置。 由于可能会发生异常事件以阻止对象的终结器运行,因此应该明确地处理该对象。

要修复违反此规则的行为,请在对对象的所有引用超出范围之前调用对象上的System.IDisposable.Dispose

请注意,您可以使用using语句(在Visual Basic中使用)来包装实现IDisposable对象。 以这种方式包裹的物体将自动放置在使用块的附近。

using (DataTable dt = new DataTable())
using (DataView dv = new DataView(dt))
{

}

在代码的第7行中,您创建了一个未使用的虚拟DataTable。 编译器抱怨DataTable和DataView对象。 更改下面的代码,它将工作。

public class Class1
{
    public class test
    {
        public void testMethod()
        {
            DataTable dt = null;
            DataView dv = null;


         try
        {
            // dt must be assigned a value only within the try block
            dt = new DataTable(dt);
            dv = new DataView(dt);
         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
            if (dv != null) dv.Dispose();

         }
        }
    }
}

更新

如果你同时处理dtdv你将得到CA2202错误 这是因为dt被处理了两次。 一旦配置dt和配置dv一次。 为避免这种情况,必须在try / catch块的末尾为dt赋值null

    try
    {
        dt = new DataTable(dt);
        dv = new DataView(dt);
        dt=null;
     }

我怀疑错误正在发生,因为您正在创建两个DataView ,并且只会丢弃其中一个:您将dv初始化为新的DataView ,然后在try块中分配另一个。 当你点击finally ,初始赋值中的那个不会被处理,因为你没有引用它。

修改你的声明DataView dv = new DataView ()只是声明变量,而不是初始化它:

public void testMethod()
{
    DataTable dt = new DataTable();
    DataView dv = null;

    try
    {
        dv = new DataView(dt);
    }
    finally
    {
        if (dt != null) dt.Dispose();
        if (dv != null) dv.Dispose();
    }
}

注意 :这直接修复了您的第二条错误消息(关于dv ),并间接解决了第一条(关于dt )。 引发第一个错误是因为,如果dv的冗余初始化是抛出异常,则不会丢弃dt - 因此删除该初始化会修复错误。

你的示例代码究竟正在演示的内容尚不清楚。

但是,如果您在遵循MSDN推荐模式时尝试在CA2000上清除误报,则有一些已知的补救措施。 在这里概述了两种情况其中简单的代码更改使代码分析能够识别推荐的模式:

  1. 临时必须命名为camelCase前面的字符串“temp”到最终目标IDisposable
  2. 最终目标IDisposable必须是函数的返回值。

可能是因为DataTable初始化器理论上可能会在处置之前中断。 您可以尝试使用null初始化它,并在try块中使用新的DataTable实例进行初始化。 毕竟你终于可以进行可空的测试了。

就像是

public class Class1
{
    public class test
    {
        public void testMethod()
        {
            DataTable dt = null;

         try
        {
            dt = new DataTable();

         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
         }
    }
    }
}

发生的原因是您在try块之外初始化dt。

public void testMethod()
{
    DataTable dt = null;
    DataView dv = null;
    try
    {
        dt = new DataTable();
        dv = new DataView(dt);
    }
    catch
    {
    }
    finally
    {
        if (dt != null) dt.Dispose();
        if (dv != null) dv.Dispose();
    }
}

}

如其他答案中所述,您也可以使用块而不是尝试...最后。

public void testMethod()
{
    using (DataTable dt = new DataTable())
    {
        using (DataTable dv = new DataView(dt))
        {
        }
    }
}

一个问题:你打算让test类成为Class1的嵌套类吗?

   public class test
    {
        public void testMethod()
        {
            DataTable dt = null;
            DataView dv = null;


         try
        {
           dv = new DataView(dt);
         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
            if (dv != null) dv.Dispose();

         }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM