0

例如:在方法中创建它并将其分配给字段。将该字段传递给方法,然后将其分配给 using 语句的变量(这是唯一Dispose被调用的)。

SqlCommand CreateSqlCommand()
{
    SqlCommand cmd1 = new SqlCommand();
    return cmd1;
}

void UseSqlCommand(SqlCommand cmd4)
{
    using (SqlCommand cmd3 = cmd4)//Is this using-statement enough?
    {
        //use cmd3 here...
    }
}

并使用:

SqlCommand cmd2 = CreateSqlCommand();
UseSqlCommand(cmd2);

额外细节:GC 是否会在下一轮收集所有这些变量?为什么不 -在这里查看 David M. Kean 的回答。

编辑

我已经添加

cmd2.CommandText = "";

在上(最后)行之后。并且没有抛出错误。

为什么?它应该已经被处理掉了!没关系。可以引用已处置的对象...

请不要专注于示例,而应专注于问题本身。谢谢。

4

4 回答 4

3

是的,在引用变量的块完成后,using 语句将调用 Dispose()。这是一件好事和坏事,假设您创建一个 sql 命令并将结果存储在一个变量cmd中,然后将该变量传递给另一个使用和处置的方法cmd。现在您遇到了一个已释放的变量,如果您尝试使用它,它可能会抛出一个ObjectDisposedException.

SqlCommand cmd = CreateSqlCommand();
UseSqlCommand(cmd);

//Uh oh, cmd can still be used, what if I tried to call UseSqlCommand(cmd) again?

在方法之外处理该对象会更加清晰和安全(就像 Jordão 发布的那样)。

using(SqlCommand cmd = CreateSqlCommand())
{
    UseSqlCommand(cmd);
}

现在您完全控制了对象并限制了它的范围。

于 2013-06-19T20:29:44.057 回答
2

using从外部控制范围:

using (SqlCommand cmd2 = CreateSqlCommand()) {
  UseSqlCommand(cmd2);
}

...

void UseSqlCommand(SqlCommand cmd4) {
  // use cmd4 here...
}

并且可能重命名UseSqlCommand为不同的名称,例如ExecuteSqlCommand.

于 2013-06-19T20:05:53.080 回答
1

using语句的目的不是处理变量,而是对象实例。变量通常用于标识对象实例,但引用类型变量不保存对象——它们保存“对象标识符”。

如果有人说例如var myPort = new System.Io.Ports.SerialPort("COM1", ...); myPort.Open()SerialPort对象将要求系统让它使用COM1串行端口,而不是让其他任何人使用它,直到另行通知。系统将为该端口生成一个句柄,并设置一些标志,以便仅允许具有该句柄的代码使用该端口。一旦创建了对象(比如系统任意为其分配了 ID #8675309),系统就会将该 ID 存储到变量中myPort)。

当代码不再需要使用该串行端口时,重要的是有人告诉对象#8675309 它不再需要,因此它可以反过来告诉系统它应该使 COM1 可用于其他应用程序。这通常通过调用Dispose一个包含对对象#8675309 的引用的变量来完成。一旦完成,每个持有对对象#8675309 的引用的变量都将持有对其Dispose方法已被调用的对象的引用。请注意,Dispose方法实际上不会影响任何这些变量(除非它们在方法本身的代码中被重写)。在调用之前持有“object #8675309”的任何变量将在之后继续这样做。该对象将释放其串行端口,因此存储这些变量的引用将不再有用,使用这些变量的代码可能希望将它们清除,但SerialPort对象不会关心一种方式或其他。

于 2013-06-20T15:26:00.303 回答
0

我认为这就是你想要做的:

public class MySqlClass : IDisposable
{
    private SqlConnection conn { get; set; }

    public MySqlClass(string connectionstring) 
    {
        conn = new SqlConnection(connectionstring);
    }

    public void DoSomething1(string tsql)
    {
        using (SqlCommand comm = new SqlCommand(tsql, conn)) {
            conn.Open();           
        }
    }

    public void DoSomething2(string tsql)
    {
        using (SqlCommand comm = new SqlCommand(tsql, conn)) {
            conn.Open();           
        }
    }

    //DISPOSE STUFF HERE    
}

利用...

using (MySqlClass MySQL = new MySqlClass()) 
{
    MySQL.DoSomething1();
    MySQL.DoSomething2();
}

* 更新 * 更新 >>>> 示例 <<<<< 要点是您在上面创建了 SqlConnection 的单个实例,并且可以重用它。该类实现了 IDisposable,因此您可以使用 using() 方法进行自动处置。比像你提到的那样传递 SqlCommand 实例更好。

于 2013-06-19T20:01:17.603 回答