2010-06-03 88 views
4

有一次,我讀的是MSDN article鼓勵下面的編程範式(它不是100%真實......看到編輯):拋出異常:封裝它們還是不封裝?

public class MyClass 
{ 
    public void Method1() 
    { 
     NewCustomException(); 
    } 

    public void Method2() 
    { 
     NewCustomException(); 
    } 

    void NewCustomException() 
    { 
     throw new CustomException("Exception message"); 
    } 
} 

你覺得這種模式是有意義的?將異常消息存儲在static const字段中,然後將它傳遞給異常的構造函數是不夠的,而不是封裝整個異常拋出?

編輯:

使用異常生成器方法。它是 常見的一類,在其 執行中拋出異常來自不同地方的 異常。爲避免過多的代碼,請使用助手方法,該方法會創建異常並將其返回。

我只注意到(見引用),該文章講述到回報異常:

public class MyClass 
{ 
    public void Method1() 
    { 
     throw NewCustomException(); 
    } 

    public void Method2() 
    { 
     throw NewCustomException(); 
    } 

    CustomException NewCustomException() 
    { 
     return new CustomException("Exception message"); 
    } 
} 

你覺得這個怎麼樣?

+0

如果您打算爲其添加額外的邏輯,您需要在其他地方添加額外的邏輯,封裝異常拋出是非常好的。 – 2010-06-03 16:35:53

+0

好的。但我的意思只是拋出異常,沒有任何邏輯。 – Simon 2010-06-03 16:37:36

+0

你有鏈接到這篇文章的機會嗎?閱讀某人推薦的背景是很好的。 – 2010-06-03 16:39:02

回答

10

我的理解是,傳遞一個異常實例是一種失算,如果沒有其他原因,你會失去與異常相關的堆棧跟蹤。調用另一個方法會改變堆棧跟蹤,從而使其無效。我建議至少讓堆棧跟蹤異常並將它作爲參數傳遞給一些幫助者,如果這是你要走下坡路的話。

+0

他不是在傳遞一個異常實例,只是把它的消息放在'const'中。 – 2010-06-03 16:37:33

4

這是我的書中的一個重構。您必須在堆棧跟蹤中返回一行以準確查看發生問題的位置。如果您的自定義例外總是使用相同的消息,請將其放在CustomException類中。如果在你引用的代碼中只有相同的內容,那麼是的,把它放在const字段中(你不能有static const - 它隱含地爲static)。

+0

Infact你不能把一個異常放入'const'字段中。 '靜態只讀'是最接近你可以得到的。 – 2010-06-03 16:36:33

+2

@Matti:他不是在談論這個異常,只是它的錯誤信息。 – 2010-06-03 16:37:07

+1

哦。如果我正確地閱讀東西,我想這會有所幫助¬__¬ – 2010-06-03 16:40:53

0

我沒有看到製作一個簡單地引發異常的方法。但是,我認爲放棄自定義異常有價值。如果您拋出的所有異常都是自定義異常的子節點,它可以讓您快速查看拋出的異常是否是您正在處理的異常或尚未處理的異常。此外,你可以趕上MyBaseException,它不像捕捉Exception差。

0

如果你不知道你打算如何處理異常,那麼這麼做很方便。你想扔掉它嗎?或者也許以後你會在某個地方記錄這個異常然後扔掉它?或者可能傳遞一些與異常綁定的參數(即方法名稱等)?

在這種情況下,創建一個處理異常情況的單獨方法在您想要更改時很方便。

我通常不會爲此感到困擾 - 相反,只是預先確定如何處理異常(即您要放置消息的字符串信息)。

2

我會建立一個Exception,而不是拋出它的方法。如下面的示例。我似乎記得看到一個微軟的指導方針,建議這個,但我不記得在哪裏。

利用這種技術,如果你想改變任何原因的異常類型,你只需要在一個地方這樣做(例如,從ConfigurationExceptionConfigurationErrorsException從.NET 1.x的升級時更改.NET 2.0) 。

此外,您還尊重DRY原則,方法是讓代碼的單個副本與其消息以及異常中包含的任何其他數據一起構建異常。

你顯然不會在瑣碎的情況下做到這一點(例如,你將不會取代由throw BuildArgumentNullException("myParamName")throw new ArgumentNullException("myParamName")

private static Exception BuildSomeException(... parameters with info to include in the exception ...) 
{ 
    string message = String.Format(...); 
    return new SomeException(message, ...); 
} 

... 
throw BuildSomeException(...); 
3

還有一個問題,你得到這樣做是會有很多的地方,你甚至不會能夠拋出異常,因爲編譯器不會允許它。考慮添加到您的類這兩種方法:

public string GetFoo1(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      NewCustomException(); 
    } 

    public string GetFoo2(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      throw new CustomException("Exception message"); 
    } 

GetFoo1將無法編譯,而GetFoo2會。

+1

+1好的一點是,如果封裝在方法中,編譯器不會看到這個throw。 – Joe 2010-06-03 16:56:45

0

我一般比較喜歡存儲異常消息資源。這有以下幾個目的:

  • 如果要求歸結爲本地化異常消息,這是一件容易的事。
  • 異常消息往往在整個開發人員中更加標準化,因爲額外的工作是創建一個新的但僅稍微不同的消息。
  • 如果您確保消息被標識符引用,並且在引發時包含該標識符和異常,那麼將消息跟蹤到拋出它的代碼會更容易。

缺點是它只是比硬編碼消息需要更多的努力。