2009-10-07 67 views
2

我讀C#article.It表明catch塊的選擇

在catch塊結束時,你有三種選擇:

•重新拋出同樣的異常,通知碼在調用堆棧中出現較高的異常。

•拋出一個不同的異常,給出更豐富的異常信息,以便在調用堆棧中更高地編寫更高的 。

•讓線脫離捕捉塊的底部。

我無法理解points.It將是一個很大的幫助,如果你給予簡單的例子說明之。

在此先感謝。

更新: 當我需要處理重新拋出異常,我需要有嵌套的try ... catch塊像

try 
{ 
    try 
    { 
    } 
    catch(InvalidOperationException exp) 
    { 
    throw; 
    } 

} 
catch(Exception ex) 
{ 
    // handle the exception thrown by inner catch block 
    // (in this case the "throw" clause  inside the inner "catch") 
} 
} 
+0

這個'c#文章',是否包含代碼示例? – 2009-10-07 09:37:46

回答

6

那麼,在這裏是在代碼那些不同的選項:

選項1:重新拋出

try 
{ 
    // Something 
} 
catch (IOException e) 
{ 
    // Do some logging first 
    throw; 
} 

選項2:拋出一個不同的異常

try 
{ 
    // Something 
} 
catch (IOException e) 
{ 
    // Do some logging first 
    throw new SorryDaveICantDoThatException("Oops", e); 
} 

選項3 :讓線脫離底部

try 
{ 
    // Something 
} 
catch (IOException e) 
{ 
    // Possibly do some logging, and handle the problem. 
    // No need to throw, I've handled it 
} 

編輯:要回答這個額外的問題,是 - 如果你需要處理重新拋出異常,需要在外部範圍進行處理,正如在問題中。儘管如此,這還不是一個好主意。事實上,catch區塊首先應該比較少見,而嵌套區域則更爲如此。

+0

不應該最後一個catch塊包含「首先執行一些**清理**」嗎? – Joren 2009-10-07 09:07:30

+5

@Joren:清理通常會在finally塊中,而不是catch塊。 – 2009-10-07 09:13:01

+0

喬恩Skeet,你是​​深入寫C#的人嗎? – user184805 2009-10-07 09:19:01

0

你也可以回到在catch塊,所以是第4選項。返回false,返回null等等(甚至返回一個默認值)。

讓catch塊落空意味着你已經成功地處理了你的try塊中引發的異常。如果你還沒有,更好的重新拋出,或以其他方式失敗。

+0

在IL水平上,這與讓它從捕獲塊底部掉下來的水平相同。你已經處理了這個異常,所以繼續執行。 – 2009-10-07 09:01:42

1

1)重新擲

try 
{ 
    ... 
} 
catch (Exception e) 
{ 
    ... 
    throw; 
} 

2)拋出一個新的異常

try 
{ 
    ... 
} 
catch (Exception e) 
{ 
    ... 
    throw new NewException("new exception", e); 
} 

3)掉出

try 
{ 
    ... 
} 
catch (Exception e) 
{ 
    ... 
} 
+2

注意:您的重新拋出的示例不正確。它應該扔掉;否則調用堆棧丟失。 – 2009-10-07 09:12:05

+0

有趣。我不知道。編輯並更新。 – 2009-10-07 09:49:17

2

這些都是選擇。 1和2之間的區別在於,如果拋出異常並且要調試到拋出的位置,那麼將通過選項1 (在特定對象的try塊中一直向下)到達那裏。對於選項2,你會和最多隻在該行(拋出新Exception2())

3是當你想忽略異常,只是繼續

//1 
catch (Exception ex) 
{ 
    throw; 
} 

//2 
catch (Exception ex) 
{ 
    throw new Exception2(); 
} 

//3 
catch (Exception ex) 
{ 
} 
return something; 
+1

選項2通常是個壞主意,您希望將捕獲到的異常作爲innerException傳遞給您正在拋出的新異常,以防調用者對引發異常的詳細信息感興趣。 – 2009-10-07 09:38:08

+0

是真實的,但這只是一個演示;) – RvdK 2009-10-07 11:08:21

0

這不是C#具體的,這是真的的任何編程語言(稱它們爲異常,稱它們爲錯誤,然後根據需要調用它們)。

因此,對您的問題的回答是,這是所有編程的基本前提,並且您必須根據錯誤,環境和要求確定在代碼中採取的正確操作。

1

重新拋出同樣的異常:

try 
{ 
    // do something that raises an exception 
} 
catch (SomeException ex) 
{ 
    // do something with ex 
    throw; 
} 

拋出一個不同的異常

try 
{ 
    // do something that raises an exception 
} 
catch (SomeException ex) 
{ 
    // do something with ex 
    throw new SomeOtherException(ex); // NOTE: please keep ex as an inner exception 
} 

讓線掉下來:

try 
{ 
    // do something that raises an exception 
} 
catch (SomeException ex) 
{ 
    // do something with ex 
} 
// the code will finish handling the exception and continue on here 
+2

當重新拋出異常時,最好使用'throw';或者在該點之前丟失堆棧跟蹤。當然,除非那是你想要的。 – Pike65 2009-10-07 09:27:07

+0

你是對的。我不知道爲什麼我輸入了,因爲我今天已經多次爭論同一個觀點。謝謝。 – rein 2009-10-07 09:31:15

2

在大多數生產系統中,你想要的最後一件事是一個真正的未處理的例外。這就是爲什麼你通常會試着去捕捉聲明。

你可能想知道爲什麼你會想要拋出一個你已經發現的錯誤,這裏有一些真實世界的例子。

  1. 您已經捕獲了WCF應用程序中的異常,記錄了該異常,然後拋出了一個faultException,而不是返回給WCF客戶端。以同樣的方式,你可能會有一個傳統的asmx,發生異常,然後拋出一個SOAP異常回到客戶端。要點是某些例外需要遵守某些規則:例如,標準的.net例外不會被WCF客戶端所消化。

  2. 你捕獲的異常深的地方你的代碼中,登錄異常,甚至可能採取了一些行動。但是,較高的在你的代碼,你有另一個例程也在等待例外,在這一點上上漲,異常可以很容易地改變業務流程。通過捕捉異常低了下去,代碼上漲是不知道有任何異常,所以你需要拋出異常背出被抓住上漲,讓你寫了代碼也可以調整工作流程。 Ofc這些都不是魔術發生的,它必須被編碼,不同的程序員使用不同的技術。

  3. 您可能還想要捕獲一個或幾個語句的異常,例如從XML文件獲取配置值,如果出現錯誤,.net可能只是返回未設置的對象引用。您可能會捕獲此,然後重新拋出異常爲「配置值:未提供客戶名稱」。

希望這會有所幫助。

+0

絕對非常有幫助 – user184805 2009-10-07 09:08:18

+0

生產或生產? – 2009-10-07 09:10:50

+1

我想說,在生產系統中,你最不想要的就是數據,因爲系統試圖繼續處理請求(或其他任何事情),即使它發現事情是錯誤的,數據也被搞砸了。這就是爲什麼try/catch塊應該很少。 – 2009-10-07 09:14:27

0

Taylor,

當你正在學習異常處理,我想添加我的2美分。拋出異常是非常昂貴的(當然,代價昂貴的是內存佔用),所以在這種情況下,您應該考慮將錯誤消息分配給一個字符串,並通過應用程序將其轉發到日誌或其他東西。

例如:

string errorMessage = string.empty; 

try 
{ 
... 
} 
catch(Exception e) 
{ 
    errorMessage = e.Message + e.StackTrace;; 
} 

這樣,你可以隨身攜帶反正這個字符串。該字符串可以是全局屬性,可以通過電子郵件發送或以文本文件記錄。

0

我認爲我們已經在這裏得到了很好的答案。

它可能是您整體架構設計的一部分(或不是),但我一直觀察到的是,您通常只捕獲可以增加價值的位置(或從錯誤中恢復) - 換句話說,不要嘗試...趕上...重複投擲多次爲一個單一的操作。

您通常應該爲您如何處理異常作爲整體設計的一部分規劃一個一致的模式或設計。在任何情況下,您都應該計劃處理異常,未處理的異常很難看!