【问题标题】:Handling IDisposables within another IDisposable "using" statement在另一个 IDisposable“使用”语句中处理 IDisposable
【发布时间】:2013-09-28 23:13:56
【问题描述】:

我对 C# 还是比较陌生,并且只是在过去几天内接触过“IDisposables”。我可以掌握using 块的概念来处理必须处理的对象,而无需手动记住调用.Dispose() 方法 - 方便!

假设我从一个新的SqlConnection 开始,我在using 语句中处理它。在该代码块中,我创建了一些额外的 IDisposable,例如 SqlDataAdapter。该适配器是否需要它自己的 using 语句?

例如,如果我有代码...

using (SqlConnection myConnection = new SqlConnection())
{
    SqlCommand myCommand = new SqlCommand();
    SqlDataAdapter myAdapter = new SqlDataAdapter();
    // Do things
}

...myCommandmyAdapter 会在 myConnection 被处理时被处理(因为它们在该代码块的范围内)?还是我需要多个using 语句,可能类似于:

using (SqlConnection myConnection = new SqlConnection())
{
    using (SqlCommand myCommand = new SqlCommand())
    {
        using (SqlDataAdapter myAdapter = new SqlDataAdapter())
        {
            // Do things
        }
    }
}

【问题讨论】:

  • 是的,您需要多个 using 块,以便在 using 块的范围结束时调用每个对象的 dispose 函数。
  • 请注意,需要记住 Dispose() 只是转移到需要记住 using() {}。这样做的主要优点是可读性和异常安全性。

标签: c#


【解决方案1】:

严格来说,确实最好将它们全部处理掉。但是,您可以通过直接嵌套它们来避免缩进:

using (var myConnection = new SqlConnection())
using (var myCommand = new SqlCommand())
using (var myAdapter = new SqlDataAdapter())
{
    // Do things
}

或者,特别是在 ADO.NET 的情况下(公平地说,它有很多一次性类型),您可能会发现使用其中一个隐藏大量管道的库更容易 - 因为例如,使用“dapper”:

using(var conn = new SqlConnection(...))
{
    return conn.Query<Customer>(
        "select * from Customers where Region=@region",
        new { region }).ToList();
}

【讨论】:

    【解决方案2】:

    该适配器是否需要它自己的 using 语句?

    在这种情况下,不。但这取决于对 Connection 和 Adapter 对象的详细了解,因此作为最佳实践:每个IDisposable 使用一个using()。即使对于 Dispose() 什么都不做的 MemoryStream。它们很便宜。

    您的代码是正确的,但我们通常会节省 {}

    using (SqlConnection myConnection = new SqlConnection())
    using (SqlCommand myCommand = new SqlCommand())    
    using (SqlDataAdapter myAdapter = new SqlDataAdapter())
    {
        // Do things
    }
    

    我们在这里使用规则,当 using() 控制 1 个语句(下一个 using())时,您不需要大括号。然后我们稍微修改一下缩进。

    【讨论】:

      【解决方案3】:

      使用只是

      的语法糖
                  var connection = new Connection();
              try
              {
                  connection.DoSomething();
              }
              finally
              {
                  // Check for a null resource.
                  if (connection != null)
                  {
                      ((IDisposable)connection).Dispose();
                  }
              }
      

      所以是的,您需要嵌套 using 语句以确保处理所有这些

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-24
        • 1970-01-01
        • 2016-04-12
        • 2018-04-04
        • 1970-01-01
        • 1970-01-01
        • 2010-09-20
        相关资源
        最近更新 更多