2010-10-22 43 views
3

捕獲所有異常並將它們作爲特定類型重新拋出是一種很好的做法 - 基本上將從應用程序的特定部分(或服務)拋出的所有異常進行分類?捕獲所有異常並將它們作爲分類方面的特定類型異常重新拋出是否是一種好的做法?

喜歡的東西:

// This class is used to label all the exceptions occured on 
// Race Cars Service calls as RaceCarsServiceException 
public class RaceCarsServiceException : Exception 
{ 

public class RaceCarsServiceException (Exception e) 
       : base("Something went wrong!", e) 
    { 
    // Basically I assign the exception e as the inner exception 
    //by using the constructor method of Exception class 
    } 

} 

public class RaceCarsService 
{ 

// Some member fields, methods etc. here 

public double GetMaxSpeed(CarModel model) 
{ 
    try 
    { 
     return (double)_carsWebService.GetMaxSpeed(model.ToString()); 
    } 

    catch(Exception e) 
    { 
     throw new RaceCarsServiceException(e); // So all exceptions are rethrown 
              //as type of RaceCarsServiceException 
    } 
} 
} 

回答

1

此代碼示例不重新拋出異常,但創建其他新一個基地。

該代碼將創建新的堆棧跟蹤。

good practice for exceptions

+0

我不同意,因爲你不知道他的結構如何實現。更多我經常需要這兩個堆棧跟蹤,因爲有多種代碼路徑可以到達相同的地方 – 2010-10-22 09:00:52

2

這是那些巨大的爭論startingt問題之一。

如果您正在拋出自定義異常,它們不應該直接從內部表達式映射,如您的示例中所示。您應該進行某種條件檢查,以區分您對特定自定義異常的具體需求,以及可能拋出的各種可能的異常。

在我看來,如果在恰當的地方適度地完成這項工作,這樣做可能會非常有益。

對於我構建的一個應用程序,我們需要能夠使用傳入的參數來追蹤每個函數調用,以便我們可以識別導致異常的精確事件鏈。

有時候內部的異常不夠細化。或者你需要拋出一個異常來告訴你什麼樣的過程失敗了。

例如,如果您的代碼必須是事務性的,但是可以跨多個服務工作,因此需要一些手工代碼來處理事務,那麼事務異常是適用的,就像事務回滾異常一樣(這意味着您是在一個痛苦的世界裏)。

無論我認識那些強烈認爲自定義異常是件壞事的人,原因在於容易被人拿走並創造太多對其他人毫無意義和無用的習慣用法。

我想到的一件事是RecordDoesNotExist異常感覺像是DAL異常,但實際上它發生並在業務邏輯中經常處理。

所以總之,我認爲他們是在適當的地方,適度和有充分理由的好主意。但它很容易與他們有點ott。

您應該始終將原始的expcetion傳遞給您的自定義異常並將其存儲在那裏。這樣可以保留堆棧跟蹤,並將堆棧跟蹤存儲在異常中的自定義堆棧拋出點。

我在審覈它們時使用自定義excpetions是一項要求。

編輯: 在對方的回答我得以下鏈接後說,這是excpetions一個偉大的文章

Exception Handling Best Practices in .NET

隨着這一個有關反 - 模式

Exception Anti-Patterns

0

沒有必要這樣做(至少在你的例子中)。當試圖調用可能拋出異常的方法時,分別處理不同類型的異常。

try 
{ 
    AMethodMayThrowExceptions(); 
} 
catch (FileNotFoundException fileEx) 
{ 
     //maybe create the file and retry 
} 
catch (TimeoutException timeoutEx) 
{ 
     //maybe a retry after n seconds 
} 
catch (Exception ex) 
{ 
     //other exceptions which I don't care 
     //just a prompt of ex.Message or something 
} 

如果您使用單個RaceCarsServiceException,會發生什麼?

catch (RaceCarsServiceException ex) 
{ 
    // now it's supposed to have a `ErrorCode` property, or an inner exception 
    if (ex.ErrorCode == ErrorCode.File) 
     //file exception, everything is the same with FileNotFoundException 
    else ... 
} 

你得到的只是麻煩和可讀性較差的代碼!

+0

但是我可以爲這種情況創建更多從RaceCarsServiceException派生的異常類型。 – pencilCake 2010-10-22 09:13:01

+0

許多內置的.net異常應該恕我直言,不會拋出用戶代碼,因爲調用'Foo'的代碼可以區分兩種非常不同的情況:(1)根據'Foo'的文檔,應該拋出'InvalidOperationException'; (2)'Foo'調用了一個拋出'InvalidOperationException'但是'Foo'的方法並沒有期待這樣的異常,並且沒有捕獲它。請注意,條件#1可能發生在'Foo'調用拋出異常'Foo' *的方法*期望的方法時。應該如何區分#1和#2? – supercat 2012-10-29 18:36:31

相關問題