2010-03-26 67 views
2

我有兩種方法,一種直接調用另一種,這兩種方法都拋出完全相同的2個異常(如果出現錯誤情況,而不是指出我收到異常)。爲此,我應該在每個try塊中使用one語句編寫獨立的try和catch塊,並捕獲這兩個異常(這兩個都可以處理,因爲我檢查了MSDN類庫引用,並且還有一些我可以執行的操作,例如,重新打開SqlConnection或者運行一個查詢,而不是一個不存在的存儲過程)。所以這樣的代碼:如何用2個方法構造代碼,一個接一個地拋出相同的兩個異常?

try 
{ 
    obj.Open(); 
} 

catch (SqlException) 
{ 
    // Take action here. 
} 


catch (InvalidOperationException) 
{ 
    // Take action here. 
} 

而且同樣的另一種方法,我直呼後。這似乎是一種非常混亂的編碼方式。另一種方法是使用異常變量進行編碼(因爲我使用AOP來記錄異常詳細信息,因此使用類級屬性,因此這種變量已被忽略)。這樣做可以幫助我找出哪種方法導致異常,然後採取相應措施。這是最好的方法,還是完全有另一種最佳做法?

我還假設,因爲只有這兩個方法被拋出,所以我不需要捕獲異常,因爲這將是我無法處理的異常(導致出我的控制的方式)。

謝謝

+2

答案可能取決於您在第一種方法拋出異常和第二種拋出異常時的處理方式。 – 2010-03-26 21:42:31

+0

也是如此。雖然似乎看到哪種方法調用拋出異常,然後做某種行爲似乎是最好的方法。我有興趣知道在設置壞習慣之前是否有其他方式。 – dotnetdev 2010-03-26 21:50:31

回答

1

除非您能夠以合理的方式處理並從錯誤中恢復,否則不應捕獲異常。考慮到這一點,你應該選擇不捕捉這些異常,否則你應該抓住它們並做一些有用的事情並繼續。

假設您正在嘗試執行後者:處理錯誤並繼續,無論兩個語句中的哪一個失敗都執行相同的事情是否有意義?假設你有這樣的:

try { 
    f1(); 
    f2(); 
} catch (FooException) { 
    // Recover from error and continue 
} 

f3(); 

在這種情況下,如果f1()失敗,並從錯誤中恢復,f2()永遠不會被執行 - 它直接到f3()。那真的是你想要的嗎?也許有時候......但通常不會。

更可能的是,在出錯f1()之後,您要麼完全退出出錯或要恢復,然後繼續執行f2()。如果是這樣,那麼你需要兩個獨立的try/catch塊。

如果您對恢復不感興趣,但只是記錄異常,那麼最簡單的方法是讓它們在更高級別上傳播並捕獲它們(但在程序崩潰或無法使用之前)並記錄消息和堆棧跟蹤。這可以確保您將記錄所有異常,並避免在每個可能拋出的方法中插入try/catch和日誌代碼。

+0

所以如果我想在清理第一個後繼續第二個方法,我應該使用單獨的try/catch塊。實際上並沒有知道這一點。這需要處理不同的清理操作。如果我不想在第一種方法的例外之後繼續,但想要進行不同的清理活動,我應該使用一個標記(例如f1ThrewException = true),或者使用stackframe對象(更昂貴)。 – dotnetdev 2010-03-26 21:59:03

+0

我想說,一旦出現問題,您確實希望終止這種做法,這種情況比較常見 - 您唯一不知道的情況恰恰是當您遇到問題時。您要重試該命令直至成功,或者失敗的部分是可選的(並且預計會失敗)。如果第一次失敗,OP似乎想繼續執行下一個命令,但它肯定不是常見的情況 - 而且通常與糟糕的設計相關聯(保留傾向於默默忽略異常的代碼極易出錯)。 – Luaan 2015-08-10 09:38:05

1

你說得對,你不應該捕捉異常。

通常,您需要儘可能多的catch子句,因爲您有不同的恢復方法。如果這兩種方法的恢復行爲不同,我發現使用每個try/catch都沒有錯。

特別考慮是否在成功恢復第一個方法後運行第二種方法。如果是這樣,你絕對不希望把第二個方法放在同一個try塊中,在那裏它將被異常跳過。

0

您可以創建一個接受Action參數的方法:

void trySomething(Action mightThrow) 
{ 
    try 
    { 
     mightThrow(); 
    } 
    catch(SqlException) 
    { 
    } 
    catch(InvalidOperationException) 
    { 
    } 
} 

然後你就可以得到拋出由mightThrow.Method.Name方法的名稱。

+0

這是一個新穎的方法 – ChrisF 2010-03-26 21:59:58

+0

你只需要注意,你不會傳遞它的lambda或者你會得到不可破譯的垃圾作爲名稱。 – 2010-03-26 22:36:03

+0

...然後你距離一個不錯的錯誤monad只有幾步之遙。這使得編寫單個的可失效命令變得輕而易舉:P – Luaan 2015-08-10 09:39:37

相關問題