2009-02-05 24 views
24

鑑於此代碼:你如何捕捉異常與「使用」在C#

using (var conn = new SqlConnection("...")) 
{ 
    conn.Open(); 
    using (var cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = "..."; 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       // ... 
      } 
     } 
    } 
} 

我習慣寫的try/catch/finally塊爲我的數據訪問,不過,我被暴露在「使用」這似乎是一個更簡單的方法。但是,我試圖弄清楚如何捕獲可能發生的異常。

您能否給我舉一個例子來說明如何捕捉異常?

編輯補充:

我被誤導,認爲「使用」是我的try/catch/finally塊的替代品。我明白,使用不會捕獲異常。那麼這是如何取代?

+2

它的不是替代品。 – 2009-02-05 22:44:55

回答

47

using不是爲了捕捉異常而設計的;它旨在爲您提供簡單的方法來圍繞需要處理的對象包裝一個try/finally。如果您需要捕捉並處理異常,那麼您需要將其擴展爲完整的try/catch/finally或將含有try/catch的內容放在整個事情中。


爲了回答您的編輯(是usingtry/catch/finally更換?),那麼不,它不是。大多數情況下,當使用一次性資源時,你不會處理那裏的異常,然後因爲通常沒有什麼用處。因此,它提供了一種便捷的方式,以確保資源得到清理,而不管您嘗試做什麼或不做什麼。

通常,處理可支配資源的代碼工作的級別太低,無法確定正確的操作是什麼,所以異常還會傳播給調用者,調用者可以決定要採取的操作(例如重試,失敗,日誌等)。 如果您要翻譯異常(也就是說,我假設您的數據訪問層正在執行的操作),那麼您會傾向於使用帶有一次性資源的catch塊。

6

使用語句與Exceptions無關。使用塊只是確保在使用塊中的對象上調用Dispose時,它將退出該塊。即:

using(SqlConnection conn = new SqlConnection(conStr)) 
{ 
    //use conn 
}//Dispose is called here on conn. 

如果打開連接會引發異常(或任何在該塊爲此事人)還是會泡到頂部,會像其他任何unhanded例外。

7

如果你想捕捉異常,你可能應該回去使用try/catch/finally。只需將.Dispose()調用放在finally塊中即可。

+1

他可以將使用封裝到try/catch-block中。如果發現錯誤,則在進入catch之前將調用Dispose(如果存在)。 – Leonidas 2009-02-05 23:17:41

+2

這是真的,但是你已經有了更多級別的縮進,並且使用語句不再那麼方便。我寧願只有一個嘗試/抓住/最終處理所有事情(但這是一件小事)。 – 2009-02-05 23:33:43

+1

但即使使用簡單的錯誤處理,編寫看起來像調用Dispose()的代碼也很容易,但在某些情況下會失敗。使用()`至少可以確保正確清理它,即使它幾乎不可能處理粒度異常處理。 – binki 2015-01-14 16:06:05

8

將所有使用語句包裝到try/catch中。像其他人一樣說,用的就是清理實現了IDisposable接口

try 
{ 

using (var conn = new SqlConnection("...")) 
{ 
    conn.Open(); 
    using (var cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = "..."; 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       // ... 
      } 
     } 
    } 
} 
} 
catch(Exception ex) 
{ 
//Handle, log, rethrow exception 
} 
+0

這是最好的嘗試/捕捉/最後並在我的終止塊中調用配置? – GregD 2009-02-05 22:45:25

3

你仍然可以趕上(或忽略)異常完全按照自己以前上課。關鍵是您不再需要擔心丟棄數據庫連接。

即,如果您的應用程序,您需要一些其他原因捕獲異常(如日誌記錄),然後繼續前進,但你不再需要這樣做,如果你只是想處理的數據庫連接:

using (SqlConnection conn = new SqlConnection(...)) 
{ 
    // do your db work here 
    // whatever happens the connection will be safely disposed 
} 

如果你想趕上其他一些原因外,你仍然可以這樣做:

try 
{ 
    using (SqlConnection conn = new SqlConnection(...)) 
    { 
     // do your db work here 
     // whatever happens the connection will be safely disposed 
    } 
} 
catch (Exception ex) 
{ 
    // do your stuff here (eg, logging) 
    // nb: the connection will already have been disposed at this point 
} 
finally 
{ 
    // if you need it 
} 
10
using (var cmd = new SqlCommand("SELECT * FROM Customers")) 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 

0語法糖
var cmd = new SqlCommand("SELECT * FROM Customers"); 
try 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 
finally 
{ 
    if (cmd != null) 
     cmd.Dispose(); 
} 

所以,當人們告訴你,「使用」是的try/catch /最後他們被暗示你應該使用長手的形式,但添加在你的catch塊替換:

var cmd = new SqlCommand("SELECT * FROM Customers"); 
try 
{ 
    cmd.CommandTimeout = 60000; 
    ... 
} 
catch (Exception ex) 
{ 
    ...//your stuff here 
} 
finally 
{ 
    if (cmd != null) 
     cmd.Dispose(); 
}