10

我想知道为什么我们using在 C# 中使用语句。我查了一下,发现它是用来执行语句然后清理对象的。所以我的问题是:如果我们打开和关闭花括号({ })来定义一个范围,这不是一回事吗?

使用声明:

using (SqlConnection conn = new SqlConnection(connString)) {
     SqlCommand cmd = conn.CreateCommand();
     cmd.CommandText = "SELECT * FROM Customers";
     conn.Open();
     using (SqlDataReader dr = cmd.ExecuteReader()) {
          while (dr.Read()) 
          // Do Something...
     }
}

大括号:

{
     SqlConnection conn = new SqlConnection(connString);
     SqlCommand cmd = conn.CreateCommand();
     cmd.CommandText = "SELECT * FROM Customers";
     conn.Open();
     {
          SqlDataReader dr = cmd.ExecuteReader();
          while (dr.Read()) 
          // Do Something...
     }
}

两种方法之间是否存在显着差异?

4

6 回答 6

5

好吧,使用(当且仅当类实现IDisposable接口时这是合法的)

using (SqlConnection conn = new SqlConnection(connString)) {
  // Some Code
  ...
}

等于这个代码块

SqlConnection conn = null;

try {
  SqlConnection conn = new SqlConnection(connString);

  // Some Code
  ...
}
finally {
  if (!Object.ReferenceEquals(null, conn))
    conn.Dispose();
}

C#的行为与 C++ 不同,因此不要像在 C++ 中那样在 C# 中使用 {...} 模式:

{
  SqlConnection conn = new SqlConnection(connString);
  ...
  // Here at {...} block exit system's behavior is quite different:
  //
  // C++: conn destructor will be called, 
  // resources (db connection) will be safely freed
  //
  // C#:  nothing will have happened! 
  // Sometimes later on (if only!) GC (garbage collector) 
  // will collect conn istance and free resources (db connection). 
  // So, in case of C#, we have a resource leak 
}
于 2013-08-14T09:37:31.263 回答
3

大括号只显示块代码

其中 as Using 指示 GC 进行处理。

任何实现 IDisposable 的类都可以与 Using 一起使用。

using 本质上将转换为(注意没有捕获)。如果有任何异常,它将被抛出。但即便如此,连接也会处理

SqlConnection conn;
try
{
    conn = new SqlConnection(connString);
}
finally
{
    if (conn != null)
        conn.Dispose();
}
于 2013-08-14T09:30:24.357 回答
1

命名空间更改名称查找,而大括号创建一个新堆栈,可以在其中创建局部变量。

于 2013-08-14T09:34:21.893 回答
1

如果您使用带有键using的版本,则 NET 平台运行方法Dispose以释放对象使用的资源。所以对象必须实现IDisposable接口。通过这种方式,您可以确定性地释放资源(不像垃圾收集器那样)。

强烈建议在Dispose方法中清理非托管资源,因为GC不会清理它。

花括号仅确定其中使用的变量的范围,但在运行时到达右括号后不会清理资源。GC根据其算法以非确定性方式执行此操作。

于 2013-08-14T09:43:37.587 回答
1

当你使用

using( ...){
... code
}

这实际上是 using 模式,c# 编译器发出代码来调用在 using 块中创建的对象实现的 dispose 方法。

所以对于任何实现 IDisposable 接口的对象,你可以使用

using(var disposableObject = new DisposableObject()){
}

当这个编译编译器将生成下面的代码

DisposableObject disposableObject = null;
try
{
   disposableObject = new DisposableObject();
}
finally{
   disposableObject.Dispose();
}

因此 using (..) 语句确保调用一次性对象的 dispose 方法,即使在 using 语句中抛出任何异常。

于 2013-08-14T09:54:43.033 回答
0

using 等同于以下

SqlConnection conn;
try
{
   conn = new SqlConnection(connString)
}

finally
{
  conn.Dispose() //using does this automatically for you
}

规则是当某些类实现时IDisposable,您可以使用 USing 块而不是 try catch,finally 模式

如果您想更深入地了解 GC 的工作原理,请阅读Jeffery Richter的这篇优秀文章

于 2013-08-14T09:27:01.337 回答