在一个“使用”块是一个SqlConnectionclosures返回或exception?

第一个问题:
说我有

using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } 

连接是否closures? 因为从技术上讲,我们从来没有return最后,因为我们之前return了。

第二个问题:
这次我有:

 try { using (SqlConnection connection = new SqlConnection(connectionString)) { int employeeID = findEmployeeID(); connection.Open(); SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); command.CommandTimeout = 5; command.ExecuteNonQuery(); } } catch (Exception) { /*Handle error*/ } 

现在,在try某个地方,我们会遇到一个错误,并且会被抓到。 连接是否仍然closures? 因为我们再次跳过try的其他代码,直接进入catch语句。

我是如何在using作品时线性思考的? 即当我们离开using范围时Dispose()是否被调用?

  1. 是。

无论哪种方式,当使用块退出(通过成功完成或通过错误)它被closures。

虽然我认为这样组织起来会更好 ,因为看到会发生什么变得更容易,即使是后来支持它的新维护程序员也是如此:

 using (SqlConnection connection = new SqlConnection(connectionString)) { int employeeID = findEmployeeID(); try { connection.Open(); SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); command.CommandTimeout = 5; command.ExecuteNonQuery(); } catch (Exception) { /*Handle error*/ } } 

是的,这两个问题。 using语句被编译成try / finally块

 using (SqlConnection connection = new SqlConnection(connectionString)) { } 

是相同的

 SqlConnection connection = null; try { connection = new SqlConnection(connectionString); } finally { if(connection != null) ((IDisposable)connection).Dispose(); } 

编辑:修复转换为一次性http://msdn.microsoft.com/en-us/library/yh598w02.aspx

这是我的模板。 您需要从SQL服务器中select数据的所有内容。 连接closures并处理,连接和执行错误被捕获。

 string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString; string selectStatement = @" SELECT TOP 1 Person FROM CorporateOffice WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%' ORDER BY IntelligenceQuotient DESC "; using (SqlConnection conn = new SqlConnection(connString)) { using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) { if (dr.HasRows) { while (dr.Read()) { Console.WriteLine(dr["Person"].ToString()); } } else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } } 

*修订date:2015-11-09 *
正如NickG所build议的那样; 如果太多的大括号是烦人的,像这样的格式…

 using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } 

那么,如果你为EA或DayBreak游戏工作,那么你也可以放弃任何换行,因为那些只是为了那些不得不回头看看你的代码以及真正关心的人? 我对吗? 我的意思是1行而不是23意味着我是一个更好的程序员,对吧?

 using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } 

唷…好的。 我从我的系统中得到了这一点,而且我自己也玩了一段时间。 继续。

当你离开使用范围时,Dispose就会被调用。 “使用”的意图是为开发人员提供一个确保资源得到处理的有保证的方法。

来自MSDN :

使用语句可以在达到using语句结束时退出,或者抛出exception,并且控制在语句结束之前离开语句块。

Using围绕被分配的对象生成try / finally,并为你调用Dispose()

它为您节省了手动创buildtry / finally块并调用Dispose()的麻烦

在你的第一个例子中,C#编译器实际上将using语句翻译成以下内容:

 SqlConnection connection = new SqlConnection(connectionString)); try { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } finally { connection.Dispose(); } 

最后,语句总是在函数返回之前被调用,所以连接总是被closures/处理。

所以,在第二个例子中,代码将被编译为以下内容:

 try { try { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } finally { connection.Dispose(); } } catch (Exception) { } 

这个exception将在finally语句中被捕获,并且连接closures。 外部catch子句不会看到exception。

我在try / catch块中写了两个使用语句,我可以看到,如果像ShaneLS 例子那样放在内部使用语句中,exception被捕获的方式也是一样的。

  try { using (var con = new SqlConnection(@"Data Source=...")) { var cad = "INSERT INTO table VALUES (@r1,@r2,@r3)"; using (var insertCommand = new SqlCommand(cad, con)) { insertCommand.Parameters.AddWithValue("@r1", atxt); insertCommand.Parameters.AddWithValue("@r2", btxt); insertCommand.Parameters.AddWithValue("@r3", ctxt); con.Open(); insertCommand.ExecuteNonQuery(); } } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error); } 

无论放在哪里,这个例外都会被捕获而没有问题。