簡體   English   中英

C#嘗試捕獲和異常處理

[英]C# Try-Catch & Exception handling

在當前項目的代碼的各個部分中,不斷使用

try
{
    //code
}
catch(Exception e)
{
    //display nicely formatted error message
}

我的問題是,假設代碼處理所有已知/假定的錯誤(例如檢查對象是否為空等),是否應該在以應用程序全局格式顯示錯誤的代碼周圍放置try-catch?

還是讓錯誤引發異常並使應用程序自然崩潰的更好的做法?

謝謝

捕獲這樣的所有異常不是一個好習慣,除了在應用程序的頂級顯示錯誤消息的頂層。 做的好,它可以保護你的程序,其為車,但合理的整體的最終用戶的感知。 相比之下,讓應用程序崩潰是最簡單的方法,可以說服最終用戶您的應用程序是不可修復的。

就異常預防而言,有兩種主要的異常-編程錯誤(空指針,類強制轉換,超出范圍等)和環境錯誤(找不到文件,網絡路徑不可用,用戶輸入錯誤等)。 )您可以並且應該避免使用第一種,並准備好處理第二種。

class PerformTask
{
    public void ConnectToDB(requiredParams)
    {


    }
}

class PerformTaskConsumer
{
   public void SomeMethod()
   {
      try
      {
         PerformTask obj = new PerformTask();
      }

      catch(RelaventExceptions)
      {

      }
   } 


}

只要可以,請避免出現異常。 如果發生異常,則將調用者要對異常進行的處理留給調用者。 呼叫者可以決定顯示有關異常的格式正確的消息,或者決定崩潰或發生任何事情。

埃里克·利珀特(Eric Lippert)有一篇關於異常的好文章。 這里

這里有兩種截然不同的思想流派,並且兩者的支持者常常為任何人都可能以其他方式相信而感到震驚和驚訝。 最后,這是一個優先事項,您的目標用戶群期望和/或願意接受什么,更重要的是,您對應用程序的了解程度。 (您的問題暗示您沒有編寫所有涉及的代碼,因此最后一點可能比您想象的要棘手。)

首先,我假設您在這里談論的是最終用戶應用程序,而不是類庫。 在沒有明確處理的類庫中捕獲異常幾乎是沒有理由的。 您始終將決定權留給呼叫者。

但是,在最終用戶應用程序中,最終的決定權取決於您,因為在呼叫鏈的上游沒有人。 在這種情況下,您有兩個廣泛的選擇:

快速失敗

有人認為,遇到錯誤時,最好讓物理上的應用程序盡快崩潰。 盡管看起來有點適得其反,但請記住遇到未處理的異常意味着什么:您實際上不知道出了什么問題; 甚至像錯誤記錄代碼這樣的簡單操作也可能會以您意想不到的方式運行。

如果您在呼叫站點正確處理了異常,則僅當發生真正非常糟糕的事情:內存不足,堆棧損壞等時,才應該收到此類“意外”錯誤。您無法真正從中恢復的事情,無論如何,因此沒有任何嘗試的意義。

優雅地失敗

其他人認為,您應該盡可能地隔離錯誤,以防止用戶丟失信息。 如果您的應用程序具有足夠的模塊化,則一個區域中的完全故障可能完全不會影響另一區域中的數據。

這是一個冒險的主張:您必須非常小心,不要讓自己處於不一致的狀態。 它要求您肯定知道失敗代碼中的任何內容都無法從代碼的其他部分更改狀態。

結論

像往常一樣,“正確”的答案可能在中間。 通常,在不一致狀態下運行的風險幾乎總是使應用程序終止的一個好原因。 當然,您可能仍希望在此處進行某種程度的日志記錄,您可以通過兩種方法完成此日志記錄。 我的喜好不是為此使用異常,而是要像thisthisthis那樣掛接到頂層的各種“未處理的異常”事件。 在這些事件處理程序中記錄您的異常,也許顯示一個“更友好的”錯誤對話框,然后讓您的應用程序關閉。 例如,我們在生產的WPF應用程序中添加了類似的內容:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             DispatcherUnhandledException="UnhandledException">


private void UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    logger.FatalException("OH NOES! Bad stuff happened, bailing out.", e.Exception);
    MessageBox.Show("holy cow something bad happened:\r\n" + e.Exception.Message);
}

但是,在某些地方捕獲所有異常可能很安全; 這主要限於無論如何都將丟棄所有數據的地方。 例如,打印或導出已經完成的操作的結果可能會“安全地”失敗,而不會對應用程序的其余部分造成不良影響。 您可能不希望僅由於用戶沒有打印機而導致應用程序崩潰。 (我什至遇到了一個第三方打印庫的情況,在該庫中,它明確地將System.Exception拋出錯誤。)但是,您必須非常小心,知道自己在做什么,並且數據是真正隔離的。從系統的其余部分開始。

給您的提示,可讓您知道將try ... catch塊放在哪里。

放置一個全局異常處理程序,以捕獲所有未處理的異常。 記錄堆棧跟蹤和異常,向最終用戶顯示歉意並關閉程序(切勿嘗試在此處繼續)。

當應用程序崩潰時,讓它運行,檢查原因並用最具體的異常處理異常。

請記住: 異常是針對異常的,而不是針對正常程序的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM