7

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

警告 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();
      }
}
4

8 回答 8

5

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

public void testMethod()
{
    using (DataTable dt = new DataTable())
    using (DataView dv = new DataView(dt))
    {
        //your work
    }
}
于 2013-05-20T11:11:40.683 回答
2

在代码的第 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 块的末尾指定nullto 。dt

    try
    {
        dt = new DataTable(dt);
        dv = new DataView(dt);
        dt=null;
     }
于 2013-05-20T11:20:19.143 回答
2

在失去范围之前从Dispose 对象

如果一次性对象在对它的所有引用超出范围之前没有显式释放,那么当垃圾收集器运行对象的终结器时,该对象将在某个不确定的时间被释放。因为可能会发生异常事件,阻止对象的终结器运行,所以应该显式地释放对象。

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

请注意,您可以使用 using 语句(在 Visual Basic 中为 Using)来包装实现IDisposable. 以这种方式包装的对象将在 using 块的末尾自动处理。

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

}
于 2013-05-20T11:12:57.700 回答
1

我怀疑错误正在发生,因为您正在创建两个DataViews,并且只有一个会被释放:您初始化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不会被处理 - 因此删除该初始化可以修复错误。

于 2013-05-20T11:17:53.183 回答
1

您的示例代码所演示的具体内容尚不清楚。

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

  1. 临时必须命名为以camelCase 形式附加到最终目的地的字符串“temp” IDisposable
  2. 最终目的地IDisposable必须是函数的返回值。
于 2013-06-21T18:10:21.993 回答
0

发生是因为您在 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();
    }
}

}

如其他答案所述,您也可以使用 using 块而不是 try...finally 。

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

一个问题:您是否打算使test该类成为嵌套类Class1

于 2013-05-20T11:57:00.100 回答
0

可能是因为理论上 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();
         }
    }
    }
}
于 2013-05-20T11:16:32.553 回答
0
   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();

         }
        }
    }
}
于 2013-05-20T12:34:57.150 回答