【问题标题】:Does a C# using statement perform try/finally?C# using 语句是否执行 try/finally?
【发布时间】:2010-04-25 21:25:17
【问题描述】:

假设我有以下代码:

private void UpdateDB(QuoteDataSet dataSet, Strint tableName)
{
    using(SQLiteConnection conn = new SQLiteConnection(_connectionString))
    {
        conn.Open();
        using (SQLiteTransaction transaction = conn.BeginTransaction())
        {
            using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM " + tableName, conn))
            {
                using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter())
                {
                    sqliteAdapter.Update(dataSet, tableName);
                }
            }
            transaction.Commit();
        }
    }
}

C# 文档指出,使用 using 语句,范围内的对象将被释放,我已经看到几个地方建议我们不需要使用 try/finally 子句。

我通常用 try/finally 包围我的连接,并且我总是在 finally 子句中关闭连接。鉴于上面的代码,假设有异常就关闭连接是否合理?

【问题讨论】:

标签: c# exception using using-statement


【解决方案1】:

You are correct; the using statement compiles to a try / finally block.

编译器将using(resource) statement; 转换为以下代码:

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      if (resource != null) ((IDisposable)resource).Dispose();
   }
}

IDisposable 的强制转换是在 ResourceType 明确实现 IDisposable 的情况下。

【讨论】:

  • 如何释放无法在 using 语句中实例化或被重用或作为输出参数传递的资源?
  • @bjan:视情况而定。
【解决方案2】:

是的,您需要使用 try/finally 或 using 语句。两者都不需要。

using statement 几乎与 try/finally 相同,只是在 C# 3 中不能重新分配给 using 块内的变量。

using (IDisposable d = foo())
{
     d = null; // Error:  Cannot assign to 'd' because it is a 'using variable'
}

以前您可以重新分配,但仍会释放原始对象,而不是新分配的对象,您还会收到以下编译警告:

可能不正确地分配给本地 'd',它是 using 或 lock 语句的参数。 Dispose 调用或解锁将发生在本地的原始值上。

【讨论】:

  • 如何释放无法在 using 语句中实例化或被重用或作为输出参数传递的资源?
【解决方案3】:

是的,using 语句几乎只是 try ... finally 块的简写。

比如这段代码……

using (MyDisposableType foo = new MyDisposableType())
{
    foo.DoSomething();
}

...将等同于以下...

{
    MyDisposableType foo = new MyDisposableType();
    try
    {
        foo.DoSomething();
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}

【讨论】:

    【解决方案4】:

    如果遇到异常,您可以假设连接将被关闭。

    【讨论】:

      【解决方案5】:

      Using() 确保在参数中实例化的项目将被丢弃,而不管在相关代码块中发生的情况。这包括关闭数据库连接,假设 SQLiteConnection 正确处理其处置。

      【讨论】:

        猜你喜欢
        • 2014-09-30
        • 2022-11-30
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 2017-07-04
        • 1970-01-01
        • 1970-01-01
        • 2018-02-24
        相关资源
        最近更新 更多