2011-11-18 47 views
0

using語句不捕獲異常。捕捉異常,你有兩個選擇:捕捉異常。您是否替換或包裝使用語句

1)解開的使用和手動實現它:

void MyFunc() 
{ 
    StreamReader myReader = null; 

    try 
    { 
     myReader = new StreamReader(path); 
     //use myReader 
    } 
    catch (Exception e) 
    { 
     //do something with exception 
    } 
    finally 
    { 
     if (myReader != null) 
      myReader.Dispose(); 
    } 
} 

或2)保留使用,並在另一個try catch塊包裝它

void MyFunc() 
{ 
    try 
    { 
     using (StreamReader myReader = new StreamReader(path)) 
     { 
      //use myReader 
     } 
    } 
    catch (Exception e) 
    { 
     //do something with exception 
    } 
} 

對我來說,第二個看起來更整潔,特別是當你有多個使用語句時,因爲它更好地描述了流程,並刪除了顯式聲明,空檢查和Dispose()調用。

但是,由於額外的嘗試抓取開銷有效地多餘,感覺不對。

什麼是標準做法?

+3

第二種方式是多餘的? – Tim

+1

由於被投票而不太適合SO,但我更喜歡後者倒置(內部的try/catch)。它完全不會影響我,它可能會導致更多的IL,而不是自己手動執行'Dispose' - 這對我來說不是那麼容易,這是「使用」開始的地方。 – 2011-11-18 09:29:55

+0

@Tim:我想我以爲IL已經設置了兩個異常處理點。一個用於外部嘗試,另一個用於隱式嘗試。 – GazTheDestroyer

回答

6

異常處理結構的開銷只是元數據。如果沒有拋出異常,則沒有運行時性能開銷。與一些其他運行時進入/離開異常處理子句在.net中是免費的。當引發異常時,運行時使用元數據和當前指令指針來確定要執行的處理子句。

我贊成第二個。釋放資源和處理異常是獨立的概念,所以它們在代碼中分離是很自然的。

+0

您是否有一些關於異常處理的文檔,在沒有異常時不會產生開銷?我的一位同事總是聲稱這是案例 –

+0

+1這個鏈接來自Marc的[Exceptions and Performance](http://www.yoda.arachsys.com/csharp/exceptions.html):我不確定它是「免費「(必須計算一個異常*拋出的時間?;-),但是... – 2011-11-18 09:38:15

0

你應該儘量避免在方法中使用「try-catch」,除非這樣做有非常明確的要求。 就像在應用程序啓動之前檢查數據庫連接一樣。

異常處理在.Net應用程序中變得非常昂貴。

然而,如果你必須那麼顯示的第二個選項更好。 再次,這是主觀的,對異常處理的要求。

如果是用於一般錯誤處理(如記錄日誌或發送錯誤郵件),則使用Global.asax。 或者至少將其限制爲Page_Error事件。

0

另一種模式是知道的 - 在創建將另一對象的所有權對象的情況下特別有用(我通常代碼vb.net,所以請原諒所有C#的錯誤)

 
class MyDisposableClass 
{ 
    SomeDisposableThing myThing; 

    MyDisposableClass() // Constructor 
    { 
    bool ok = false; 

    try 
    { 
     myThing = new SomeDisposableThing(); 
     ... do some other stuff 
     ok = true; 
    } 
    finally 
    { 
     if (!ok) 
     { 
     zap(ref myThing); 
     } 
    } 
    } 
    static void zap<T>(ref T thing) where T:IDisposable,class 
    { 
    T oldValue = System.Threading.Interlocked.Exchange(thing, null); 
    if (oldValue != null) 
     oldValue.Dispose(); 
    } 
} 

注意雖然人們可以捕獲並重新拋出在構造函數中發生的任何異常,但如果除非重新拋出它,否則不會對異常做任何事情,最好不要捕獲異常而是捕獲和重新拋出。