2012-02-27 64 views
16

我有以下代碼:捕獲異常,添加數據,並重新拋出

try 
{ 
    OnInitialize(); 
} 
catch (PageObjectLifecycleException exception) 
{ 
    exception.OldLifecycleState = CurrentLifecycleState; 
    exception.RequestedLifecycleState = LifecycleState.Initialized; 
    throw exception; 
} 

我捕捉異常,更多的數據添加到它,並重新拋出。 ReSharper的警告我(正確地)一個重新拋出可能是打算和建議其更改爲:

throw; 

但我想知道:這是否會正確地重新拋出修改異常或未經修改的原始一個?

編輯:作爲對「嘗試它並看到」的迴應:我是C#的新手,來自C++。在C++中,你經常會在像這樣的角落案例中發現未定義的行爲,而且我感興趣的是我想要的究竟是它的正式工作方式。

+6

試一試,看看會發生什麼? – 2012-02-27 15:31:36

+0

它會重新引用任何引用指向 - 在你的情況下修改「異常」。 – 2012-02-27 15:31:59

回答

8

它會拋出引用修改的異常。

但是我不確定這是否是很好的編程風格。考慮創建一個新的異常並添加PageObjectLifecycleException作爲它的內部異常。這樣處理代碼可以確定它是否具有正確的附加信息。

+0

我也是,這是一個真正的bug。例如,外部catch塊阻止從較深層次傳回的數據。 – 2012-02-27 15:44:16

+0

代碼示例已簡化。現有數據將不會被覆蓋,只會提供一些缺失的附加數據。 – 2012-02-27 15:58:59

+0

@TonyHopkinson'Exception.Data'聽起來好像是爲了這個目的([here](https://msdn.microsoft.com/en-us/library/system.exception.data(v = vs.110) ).aspx)) – drzaus 2017-03-09 19:48:38

2

當前異常被重新拋出,雖然我不確定你的模式是一個非常好的和可維護的。

22

我知道答案已經被選中,但這裏有更多關於這個主題的信息。

try { 
    // code 
} 
catch(Exception e) { 
    throw e; 
} 

上述代碼時編譯成IL會產生到throw呼叫傳遞一個參考處理的異常作爲參數。正如你可能知道的那樣,你可以在代碼中的任何地方調用throw來引發異常。

try { 
    // code 
} 
catch(Exception e) { 
    throw; 
} 

上面的代碼在編譯成IL時會產生一個調用rethrow。這與throw不同,因爲rethrow用於表示由於某種原因決定不處理異常的塊,因此應該將責任提供給更高階的catch塊(下一個塊)。

rethrow方法保留當前調用堆棧跟蹤,以便可以跟蹤異常的來源。但是,throw方法會啓動一個新的調用堆棧跟蹤。我認爲,一旦你明白這兩種方法是用來做什麼的,這是有道理的。

以我的經驗,你使用throw exception;當你想拋出一個異常,出於某種原因(例如對象的驗證失敗),並且您已經執行了一些日誌記錄(即,當你仍然有後,你會在catch語句中使用throw;在將異常處理責任傳遞給更高級別之前,訪問未通過驗證的對象中的有用信息)。

在你的例子中,我會建議如果你需要添加更多的信息到異常,你有一個案例來創建一個全新的異常並提高它。所以你會使用throw exception;方法,其中「異常」是一個新的異常,包含額外的信息和最初拋出的異常。

希望有幫助!

詹姆斯

9

您可以添加額外的信息轉換成數據,並再次引發與throw因此它保留了其原有形態異常和調用堆棧

try 
{ 
    ... 
} 
catch (PageObjectLifecycleException exception) 
{ 
    exception.Data.Add("additional data", "the additional data"); 
    throw; 
} 
+2

這應該是公認的答案,這就是'Data'的用途。只要有人防範關鍵衝突,並且記住字典中包含的任何信息都可以在呼叫鏈中傳播,並且可以在此過程中進行修改,這是添加有用信息以便於調試的好方法。 – 2017-05-26 12:12:08

相關問題