共用方式為


建立和擲回例外狀況 (C# 程式設計手冊)

更新:2007 年 11 月

例外狀況可用於指出程式執行時所發生的錯誤。會建立描述錯誤的例外狀況物件,然後使用 throw 關鍵字「擲回」(Thrown)。然後執行階段會搜尋最適合的例外處理常式。

程式設計人員應該設計在下列一個或多個條件為 True 時擲回例外狀況:

  • 方法無法完成本身定義的功能。

    例如,方法的參數值無效:

    static void CopyObject(SampleClass original)
    {
        if (original == null)
        {
            throw new System.ArgumentException("Parameter cannot be null", "original");
        }
    
    }
    
  • 在物件某種狀態下,對物件進行不當的呼叫。

    例如可能會嘗試寫入唯讀檔案的範例。在物件狀態不允許作業的狀況下,會擲回 InvalidOperationException 的執行個體或依據此類別衍生的物件。這是擲回 InvalidOperationException 物件的方法範例:

    class ProgramLog
    {
        System.IO.FileStream logFile = null;
        void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {}
    
        void WriteLog()
        {
            if (!this.logFile.CanWrite)
            {
                throw new System.InvalidOperationException("Logfile cannot be read-only");
            }
            // Else write data to the log and return.
        }
    }
    
  • 當方法引數會造成例外狀況時。

    在這種情況下,應攔截原始的例外狀況,並應建立 ArgumentException 執行個體。原始的例外狀況應該做為 InnerException 參數傳遞至 ArgumentException 的建構函式 (Constructor):

    static int GetValueFromArray(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch (System.IndexOutOfRangeException ex)
        {
            System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);
            throw argEx;
        }
    }
    

例外狀況會包含名為 StackTrace 的屬性。這個字串包含目前呼叫堆疊上方法的名稱,以及針對每個方法擲回例外狀況所在的檔案名稱及行號。Common Language Runtime (CLR) 會在出現 throw 陳述式 (Statement) 的位置自動建立 StackTrace 物件,因此例外狀況必須從堆疊追蹤應有的起始點擲回。

所有的例外狀況都包含名為 Message 的屬性。這個字串應該設定為說明例外狀況的原因。請注意,訊息文字中不應該放入安全性的敏感資訊。除了 Message 以外,ArgumentException 也包含名為 ParamName 的屬性,該屬性應設為引發例外狀況擲回的引數名稱。若為屬性 setter,則 ParamName 應設為 value。

公用和受保護的方法一旦未能完成預期的功能,即應擲回例外狀況。擲回的例外狀況類別,應該是符合錯誤狀況的最特定可用例外狀況。這些例外狀況應記載為類別功能的一部分,而且衍生類別 (Derived Class) 或更新後的類別也應該維持與原始類別相同的行為,以保有回溯相容性 (Backward Compatibility)。

擲回例外狀況時應該要避免的做法

下列清單會指出擲回例外狀況時應該要避免的做法:

  • 例外狀況不應在一般執行時用來變更程式流程。例外狀況只應該用來報告和處理錯誤狀況。

  • 例外狀況不應在擲回以外,做為傳回值或參數傳回。

  • 請勿從自己的原始程式碼蓄意擲回 System.ExceptionSystem.SystemExceptionSystem.NullReferenceExceptionSystem.IndexOutOfRangeException

  • 請勿建立可以在偵錯模式中擲回,但是不能在發行模式中擲回的例外狀況。若要在開發階段期間辨識執行階段錯誤,請改用 Debug Assert。

定義例外狀況類別

程式可以擲回 System 命名空間 (Namespace) 中的預先定義例外狀況類別 (除了之前所註明者),或是從 ApplicationException 衍生以建立其本身的例外狀況類別。衍生類別應至少定義四個建構函式:一個是預設建構函式、一個設定訊息屬性,一個則同時設定 MessageInnerException 屬性。第四個建構函式則是用來序列化例外狀況。新的例外狀況類別應該是可序列化的。例如:

[Serializable()]
public class InvalidDepartmentException : System.Exception
{
    public InvalidDepartmentException() { }
    public InvalidDepartmentException(string message) { }
    public InvalidDepartmentException(string message, System.Exception inner) { }

    // Constructor needed for serialization 
    // when exception propagates from a remoting server to the client.
    protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context) { }
}

除非新屬性提供的資料有助於解析例外狀況,否則不應隨意將新屬性加入至例外狀況類別。如果您將新屬性加入到衍生的例外狀況類別中,則應覆寫 ToString() 以傳回新增的資訊。

C# 語言規格

如需詳細資料,請參閱 C# 語言規格中的下列章節:

  • 8.9.5 throw 陳述式

  • 8.10 try 陳述式

  • 16 例外狀況

請參閱

概念

C# 程式設計手冊

參考

例外狀況和例外處理 (C# 程式設計手冊)

例外處理 (C# 程式設計手冊)