【问题标题】:Object is not disposed along all execution paths对象未沿所有执行路径放置
【发布时间】:2014-11-14 16:32:43
【问题描述】:

我有以下代码。

private DataTable LoadSMSCellProviders()
{
    string sqlQuery = "Select * from SMSAddress";
    DataTable dt = new DataTable();
    using (SqlConnection conn = new SqlConnection(Utility.ConnString))
    {
        using (SqlCommand command = new SqlCommand(sqlQuery, conn))
        {
            SqlDataAdapter adapter = new SqlDataAdapter(command);
            adapter.Fill(dt);
            return dt;
        }
    }
}

Microsoft 代码分析告诉我,dt 并未沿所有执行路径进行处理,但我不确定如何更正此问题。如果我尝试在return 之前调用dispose,它将返回一个空值,如果我尝试在方法结束时执行此操作,则代码永远不会到达...

我在这里错过了什么?

这是来自分析工具的消息:

警告:CA2000:Microsoft.Reliability:在方法“x.x()”中,对象 'dt' 不会沿所有异常路径进行处理。称呼 System.IDisposable.Dispose 在对象“dt”上的所有引用之前 超出范围。

【问题讨论】:

  • 这个想法是,如果发生异常,您需要将其处理掉。
  • LoadSMSCellProviders()的调用方法负责处理返回的DataTable

标签: c# c#-4.0


【解决方案1】:

您需要在发生异常时处理它。像这样。

private DataTable LoadSMSCellProviders()
{
    string sqlQuery = "Select * from SMSAddress";
    DataTable dt = null;
    try
    {
        dt = new DataTable();
        using (SqlConnection conn = new SqlConnection(Utility.ConnString))
        {
            using (SqlCommand command = new SqlCommand(sqlQuery, conn))
            {
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                adapter.Fill(dt);
                return dt;
            }
        }
    }
    catch
    {
        if(dt != null)
            dt.Dispose();
        throw;
    }
}

这个想法是,如果发生异常,则无法处理 DataTable,因为它不会被传递回调用者。所以,这就是让代码分析愉快的模式。

【讨论】:

  • 即使没有发生异常,您的代码也会处理数据表!
  • 为什么不对 DataTable 也使用 using 语句?
  • 应该是try catch,而不是try finally
  • @Sean 是的,我现在已经解决了。
  • @Selman22:因为您只想在异常情况下处理它,并非总是如此。
【解决方案2】:

启动工具。 DataTables 不需要被释放。它们是 IDisposable,因为它们继承了 IComponent,但它们的 Dispose() 方法什么也不做。我觉得很恶心,MS自己的工具不知道这一点。

【讨论】:

    【解决方案3】:

    代码分析警告您该对象可能不会被释放。正如@juharr 正确建议的那样,您应该中和发生异常的代码路径,否则该对象将不会被返回并且不会被显式处理。这将消除警告。

    【讨论】:

    • 抛出异常时专门调出执行路径。
    • 据我记得,即使你的 try-catch 仍然会抱怨,因为有一个代码路径,对象超出范围而没有被处置(你返回它的那个)。
    • 不,它不应该抱怨退回未处理的一次性物品。
    • 谢谢。我刚刚测试,你是绝对正确的。上次我检查它是很久以前的事了,毫无疑问我在没有意识到的情况下错误地实现了该模式。
    【解决方案4】:

    检查@juharr 的答案,并且在您使用数据表之后,您不再需要它了

    using(dt){}
    

    它会为你处理它

    【讨论】:

    • 该方法返回的是DataTable,你不应该丢弃它!
    • @Andrew 我在他使用 DT 后明确了自己,而不是在方法中。这是一个友好的提醒,因为我们在星期五:D
    • 但是您应该知道您最后一次使用DataTable 的确切时间。我个人从未见过没有内联对象创建的using
    • 我同意该方法的调用者也应该处理 DataTable 最好使用 using 语句,除非它被传递到另一个级别,当然。
    • 我总是使用 using(包括 OP 问题中的这种行为)来提醒我总是必须使用 using(任何其他正常生活案例)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多