Effective C# 為應用程式建立特定的異常類

來源:互聯網
上載者:User
異常是一種的報告錯誤的機制,它可以在遠離錯誤發生的地方進行處理錯誤。所有關於錯誤發生的的資訊必須包含在異常對象中。在錯誤發生的過程中,你可能想把底層的錯誤轉化成詳細的應用程式錯誤,而且不丟失關於錯誤的任何資訊。你須要仔細考慮關於如何在C#應用程式中建立特殊的異常類。第一步就是要理解什麼時候以及為什麼要建立新的異常類,以及如何構造繼承的異常資訊。當開發人員使用你的庫來寫catch語句時,他們是基於特殊的進行時異常在區別為同的行為的。每一個不同的異常類可以有不同的處理要完成:  try {
Foo( );
Bar( );
} catch( MyFirstApplicationException e1 )
{
FixProblem( e1 );
} catch( AnotherApplicationException e2 )
{
ReportErrorAndContinue( e2 );
} catch( YetAnotherApplicationException e3 )
{
ReportErrorAndShutdown( e3 );
} catch( Exception e )
{
ReportGenericError( e );
}
finally
{
CleanupResources( );
}

不同的catch語句可以因為不同的運行時異常而存在。你,做為庫的作者,當異常的catch語句要處理不同的事情時,必須建立或者使用不同的異常類。如果不這樣,你的使用者就只有唯一一個無聊的選擇。在任何一個異常拋出時,你可以掛起或者中止應用程式。這當然是最少的工作,但樣是不可能從使用者那裡贏得聲望的。或者,他們 可以取得異常,然後試著斷定這個錯誤是否可以修正: try {
Foo( );
Bar( );
} catch( Exception e )
{
switch( e.TargetSite.Name )
{
    case "Foo":
      FixProblem( e );
      break;
    case "Bar":
      ReportErrorAndContinue( e );
      break;
    // some routine called by Foo or Bar:
    default:
      ReportErrorAndShutdown( e );
      break;
}
} finally
{
CleanupResources( );
}

這遠不及使用多個catch語句有吸引力,這是很脆弱的代碼:如果只是常規的修改了名字,它就被破壞了。如果你移動了造成錯誤的函數調用,放到了一個共用的工具函數中,它也被破壞了。在更深一層的堆棧上發生異常,就會使這樣的結構變得更脆弱。

 在深入討論這一話題前,讓我先附帶說明兩個不能做承諾的事情。首先,異常並不能處理你所遇到的所有異常。這並不是一個穩固指導方法,但我喜歡為錯誤條件拋出異常,這些錯誤條件如果不立即處理或者報告,可能會在後期產生更嚴重的問題。例如,資料庫裡的資料完整性的錯誤,就應該生產一個異常。這個問題如果忽略就只會越發嚴重。而像在寫入使用者的視窗位置失敗時,不太像是在後來會產生一系列的問題。返回一個錯誤碼來指示失敗就足夠了。

其次,寫一個拋出(throw)語句並不意味會在這個時間建立一個新的異常類。我推薦建立更多的異常,而不是只有少數幾個常規的自然異常:很從人好像在拋出異常時只對System.Exception情有獨鐘。可惜只只能提供最小的協助資訊來處理調用代碼。相反,考慮建立一些必須的異常類,可以讓調用代碼明白是什麼情況,而且提供了最好的機會來恢複它。

再說一遍:實際上要建立不同的異常類的原則,而且唯一原因是讓你的使用者在寫catch語句來處理錯誤時更簡單。查看分析這些錯誤條件,看哪些可以放一類裡,成為一個可以恢複錯誤的行為,然後建立指定的異常類來處理這些行為。你的應用程式可以從一個檔案或者目錄丟失的錯誤中恢複過來嗎?它還可以從安全許可權不足的情況下恢複嗎?網路資源丟失又會怎樣呢?對於這種遇到不同的錯誤,可能要採取不同的恢複機制時,你應該為不同的行為建立新的異常類。

因此,現在你應該建立你自己的異常類了。當你建立一個異常類時,你有很多責任要完成。你應該總是從System.ApplicationException類派生你的異常類,而不是System.Exception類。對於這個基類你不用添加太多的功能。對於不同的異常類,它已經具有可以在不同的catch語句中處理的能力了。

但也不要從異常類中刪除任何東西。ApplicationException 類有四個不同的建構函式: // Default constructor
public ApplicationException( );

// Create with a message.
public ApplicationException( string );

// Create with a message and an inner exception.
public ApplicationException( string, Exception );

// Create from an input stream.
protected ApplicationException(
SerializationInfo, StreamingContext );

當你建立一個新的異常類時,你應該建立這個四建構函式。不同的情況調用不同的構造方法來構造異常。你可以委託這個工作給基類來實現: public class MyAssemblyException :
ApplicationException
{
public MyAssemblyException( ) :
    base( )
{
}

public MyAssemblyException( string s ) :
    base( s )
{
}

public MyAssemblyException( string s,
    Exception e) :
    base( s, e )
{
}

protected MyAssemblyException(
    SerializationInfo info, StreamingContext cxt ) :
    base( info, cxt )
{
}
}
 

建構函式須要的這個異常參數值得討論一下。有時候,你所使用的類庫之一會發生異常。調用你的庫的代碼可能會取得最小的關於可能修正行為的資訊,當你簡單從你使用的異常上傳參數時: public double DoSomeWork( )
{
// This might throw an exception defined
// in the third party library:
return ThirdPartyLibrary.ImportantRoutine( );
}

當你建立異常時,你應該提供你自己的庫資訊。拋出你自己詳細的異常,以及包含源異常做為它的內部異常屬性。你可以提供你所能提供的最多的額外資訊:' public double DoSomeWork( )
{
try {
    // This might throw an exception defined
    // in the third party library:
    return ThirdPartyLibrary.ImportantRoutine( );
} catch( Exception e )
    {
      string msg =
        string.Format("Problem with {0} using library",
          this.ToString( ));
      throw new DoingSomeWorkException( msg, e );
    }
}
}

這個新的版本會在問題發生的地方建立更多的資訊。當你已經建立了一個恰當的ToString()方法時(參見原則5),你就已經建立了一個可以完整描述問題發生的異常對象。更多的,一個內聯異常顯示了產生問題的根源:也就是你所使用的第三方庫裡的一些資訊。

這一技術叫做異常轉化,轉化一個底的層異常到更進階的異常,這樣可以提供更多的關於錯誤的內容。你越是建立多的關於錯誤的額外的資訊,就越是容易讓它用於診斷,以及可能修正錯誤。通過建立你自己的異常類,你可能轉化底層的問題到詳細的異常,該異常包含所詳細的應用程式資訊,這可以協助你診斷程式以及儘可能的修正問題。

希望你的應用程式不是經常拋出異常,但它會發生。如果你不做任何詳細的處理,你的應用程式可能會產生預設的.Net架構異常,而不管是什麼錯誤在你調用的方法裡發生。提供更詳細的資訊將會讓你以及你的使用者,在實際應用中診斷程式以及可能的修正錯誤大有協助。若且唯若對於錯誤有不同的行為要處理時,你才應該建立不同的異常類。你可以通過提供所有基類支援的建構函式,來建立全功能的異常類。你還可以使用InnerException屬性來承載底層錯誤條件的所有錯誤資訊。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.