2011-09-14 15 views
2

我嘗試將異常邏輯放在一個系統的一部分可以回退到意外行爲上。通過「拋出新的」來處理異常,最佳實踐是什麼?它已經被處理了

該工作應該由一個新類完成,該類繼承Exception對象,並用一個新的「出口」擴展功能,該出口由用戶的錯誤信號和日誌記錄例程組成。

我可能需要了解使用throw更好,但我以爲我可以使它相當通過即,該透明:

public SomeObject GetVersion(byte p) 
{ 
    switch ((SomeObject)p) 
    { 
     case Version.SomeType1: 
      ... 
      break; 
     case Version.SomeType2: 
      ... 
      break; 
     default: 
      throw new UnexpectedQueryException(this.someOtherObject, errorCode); 
    } 
    return (SomeObject)p; 
} 

我想你可以看到什麼,我想在這裏做。

我試圖拋出應用程序無法提供請求時。這個throw意味着通過異常執行執行(這會爲調用者生成足夠的錯誤代碼)。這個例子是一個類型爲「我知道你給了我一個9但是隻允許1-8的錯誤」的錯誤,「errorCode進一步發送給UnexpectedQueryException(...)

不幸的是,應用程序將throw作爲未處理並關閉了我的線程,並且應用程序在重新啓動之前不會運行。除了這種情況,我也使用這個拋出語句。

在我眼裏,這是非常處理。

這裏最好的做法是什麼?
我想異常處理是一個「回退」,以激活不同的情況下(如上),所以我總是有一個簡單的方法來傳達一個錯誤回到用戶(這意味着我可以發送非常確切的信息,例外)。

此外,我當然希望應用程序繼續工作。

從異常邏輯代碼的一部分,

public class UnexpectedQueryException: CommunicationException 
{ 
    public UnexpectedQueryException(SomeObject object, ErrorCode errorCode) : base("UnexpectedQueryException", object, errorCode) 
    { 
    ......... 
    } 
} 

,反過來,繼承基礎異常對象,

public class CommunicationException : Exception 
{ 
    ..some fields.. 

    public CommunicationException(string Message, SomeObject object, ErrorCode errorcode) 
    { 
    ..... 
    } 
    public CommunicationException() : base("CommunicationException") 
    { } 
} 
+0

您應該發佈調用'GetVersion'的代碼,然後處理異常。沒有任何跡象表明你已經處理了例外! –

+0

@丹,謝謝。我認爲這個評論需要給我更好的解釋。拋出新的Unex..Exception()'時會發生什麼事情,如果不是將執行過程移入它呢? GetVersion在一個try/catch塊內部被調用,而這個塊又有一個'拋出新的Unexp ..()'在它的catch中。 – Independent

回答

6

如果你在你的代碼拋出一個異常,你需要趕上它並做點什麼與它 - 如果你不這樣做,你有不是處理它。

如果拋出catch塊,則同樣適用。你已經拋出了一個異常,它會繼續傳播直到找到合適的catch塊。如果不存在,則不處理。

您需要構建你的較高水平(UI)的代碼,以便它捕獲正確類型的異常並傳達你要返回給用戶的信息:

try 
{ 
    // code that can throw 
} 
catch(VerySpecificException ex) 
{ 
    // communicate to user details about VerySpecificException. 
    // possibly log. 
    // Do not re-throw or throw a new excpetion as it is now handled. 
} 
catch(AnotherSpecificException ex) 
{ 
    // communicate to user details about AnotherSpecificException. 
} 
catch(LessSpecificException ex) 
{ 
    // communicate to user details about LessSpecificException. 
} 
catch(EveLessSpecificException ex) 
{ 
    // communicate to user details about EvenLessSpecificException. 
} 
+0

啊!我明白。扔在那裏發送執行到最近的catch語句。如果我拋出一個捕獲,它只是去圈。所以,我有一些在UnexpectedQuery中處理..()。最近的Catch條款應該做什麼?(我知道它不應該拋出,在這種情況下) – Independent

+0

@Jonas - 不是圈 - 它上升到堆棧,不會保持在同一個try {} catch {}塊中。你可以在'catch'塊內嵌套'try {} catch {}',但這在代碼示例中沒有意義。 – Oded

+0

謝謝!是!在這種情況下,不需要嵌套捕獲,雖然在其他地方 - 在我得到這個「後備」工作後,如預期的那樣。到目前爲止,我的代碼仍然處理未處理的行。看起來,捕獲需要在有拋出的程序中? – Independent

-3

不幸的是,應用程序採取奉送未處理並關閉 我的線程和應用程序將不會運行,直到重新啓動。除了這個 的情況,我也使用這個拋出語句。

您提供總會拋出一個異常,因爲你試圖型字節的值類型轉換爲引用類型型someObj中代碼:

public SomeObject GetVersion(byte p) 
{ 
    switch ((SomeObject)p) 
    { 
     case Version.SomeType1: 
      ... 
      break; 
     case Version.SomeType2: 
      ... 
      break; 
     default: 
      throw new UnexpectedQueryException(this.someOtherObject, errorCode); 
    } 
    return (SomeObject)p; 
} 
+0

這個異常肯定不會是意外的查詢異常 –

+0

「..因爲您試圖將類型字節的值類型轉換爲類型SomeObj的引用類型..」 - 當然,這不是問題的一部分。只是對一些命名的快速修改。 – Independent

+3

-1你很挑剔,完全無視問題。 – Oded

3

您需要了解如何以及何時捕捉異常。

在(worker)線程中拋出異常的令人討厭的事情是,任何頂級異常處理程序(例如program.cs中的try/catch)都不會捕獲並記錄線程中拋出的異常。因此,你應該總是在線程入口方法中有一個通用的try/catch,至少如果你不希望你的應用程序死掉。

一個非常簡單的規則是,您應該只捕獲您可以處理的異常,以便從方法中提供預期結果。並在入口處防止應用程序死亡(但有時最好讓應用程序死掉)。

要了解例外更好,你可能想了解我的例外博客文章:http://blog.gauffin.org/tag/exceptions/

+0

謝謝!我在那裏一個小時前。由於我碰巧已經是這些原則的粉絲,因此沒有太多新聞。還有一些經驗和想法,通常用作提醒。 – Independent

1

一個throw不處理錯誤,但它提出了一個。沒有throw沒有錯誤處理。

您通過捕獲異常來處理異常。您需要在代碼中的某處調用GetVersion(或調用調用GetVersion等的代碼的某處)的某個try - catch塊。如果在調用層次結構中沒有捕獲到UnexpectedQueryException,則它將被處理並且您的應用程序將停止。

一個調用GetVersion不同時間(不處理異常)的示例。

List<SomeObject> GetAllVersions(byte[] bytes) 
{ 
    var result = new List<SomeObject>(); 

    foreach (byte b in bytes) 
    { 
     result.Add(GetVersion(b)); 
    } 

    return result; 
} 

現在就看你哪裏來處理異常。你可以做它的循環中,讓你得到一個結果,包含所有成功檢索對象:

foreach (byte b in bytes) 
{ 
    try 
    { 
     result.Add(GetVersion(b)); 
    } 
    catch (UnexpectedQueryException e) 
    { 
     // this is where your exception handling starts 
     // display an error, log the exception, ... 
    } 
} 

或者你可以在你的應用程序,例如另一個層次處理異常包調用GetAllVersionstry-catch塊:

List<SomeObject> = null; 
try 
{ 
    versionList = GetAllVersions(bytes) 
    // do something with versionList 
} 
catch (UnexpectedQueryException e) 
{ 
    // this is where your exception handling starts 
    // display an error, log the exception, ... 
    // Note that versionList will be null in error case 
} 

這是例外的主要優勢。他們在整個調用堆棧中傳播。所以你不需要在錯誤發生後在代碼行中處理它,但是在你的應用程序中你認爲合適的地方。