在C#中使用Using的不同方式

15

我一直在研究在C#中使用using语句,我想知道以下代码是否等效:

using (SqlConnection connection1 = new SqlConnection(), connection2 = new SqlConnection())
{
}

对于这段代码:

using (SqlConnection connection1 = new SqlConnection())
using (SqlConnection connection2 = new SqlConnection())
{
}

我会说它们是一样的,但我可能错了...不过你可以试一下。 - Nate
两者是等价的。请参见以下 SO 问题:https://dev59.com/F3M_5IYBdhLWcg3wjj4p - Michael Goldshteyn
9
我个人认为第二个更容易阅读。 - Bryan
6个回答

27

根据C#规范

当资源获取采用局部变量声明形式时,可以获取给定类型的多个资源。 一个以以下形式的using语句:

    using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) statement

精确等同于嵌套使用多个 using 语句:

    using (ResourceType r1 = e1)
       using (ResourceType r2 = e2)
          ...
             using (ResourceType rN = eN)
                statement

7

当然,在第一次和第二次使用之间,您可以插入一些代码,该代码在创建connection2之前使用connection1。

但是,由于您没有这样做,因此它们之间没有区别。它们都会产生相同的IL:

IL_0000:  newobj      System.Data.SqlClient.SqlConnection..ctor
IL_0005:  stloc.0     
IL_0006:  newobj      System.Data.SqlClient.SqlConnection..ctor
IL_000B:  stloc.1     
IL_000C:  leave.s     IL_0018
IL_000E:  ldloc.1     
IL_000F:  brfalse.s   IL_0017
IL_0011:  ldloc.1     
IL_0012:  callvirt    System.IDisposable.Dispose
IL_0017:  endfinally  
IL_0018:  leave.s     IL_0024
IL_001A:  ldloc.0     
IL_001B:  brfalse.s   IL_0023
IL_001D:  ldloc.0     
IL_001E:  callvirt    System.IDisposable.Dispose
IL_0023:  endfinally  

5

是的,这两个代码片段是等价的。

编辑

我刚刚用Reflector测试了一下。两个版本发出完全相同的IL,并且Reflector反编译成以下C#:

using (new SqlConnection())
{
    using (new SqlConnection())
    {
    }
}

也就是说,对于两个版本,即使其中一个在构造函数中抛出异常,Dispose方法也会在两个实例上被调用。

5

根据C#语言规范第8.13节的规定:

当资源获取采用局部变量声明形式时,可以获取给定类型的多个资源。形如

using (ResourceType r1 = e1, r2 = e2, ..., rN = eN)

的using语句等价于嵌套的using语句序列:

using (ResourceType r1 = e1)
using (ResourceType r2 = e2)
...
using (ResourceType rN = eN)
    statement


3

是的,它们完全相同。您可以使用Reflector来证明这一点。

    public void Method1()
    {
        using (SqlConnection connection1 = new SqlConnection())
        using (SqlConnection connection2 = new SqlConnection())
        {
        }
    }

    public void Method2()
    {
        using (SqlConnection connection1 = new SqlConnection(), connection2 = new SqlConnection())
        {
        }
    }

1
除了其他答案中提到的 C# 8.13 的优秀之处,当其中一个资源必须更改类型时,单子句情况也将不得不被重写。
using( S r1 = new S(), r2 = new S() )
{
  ...
}

当需要将 r2 更改为新类型时,必须执行以下操作

using( S r1 = new S() )
using( T r2 = new T() )
{
  ...
}

所以最好使用后者。 (个人认为,它的阅读效果更好)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接