2013-03-07 86 views
3

也許在C#中對我來說最神祕的事情是Exception類的消息屬性是隻讀的。可能是因爲我不明白這個原因,當我嘗試創建從異常派生的合理的異常類時,我很沮喪。爲什麼異常消息屬性是隻讀的?

例如(實際上我正在嘗試做什麼),我想創建一個異常以在嘗試連接到OPC服務器時引發。如果嘗試失敗,則會引發OPCException類型的對象,但我想給用戶提供更多信息。所以,我有一個名爲OPCCaException的類,它有三個參數:原始異常的返回碼,服務器名稱和主機名。

public class OPCCaException : Exception 
{ 
    public OPCCaException(ReturnCode returnCode, string serverName, string nodeName) 
    { 
     if (nodeName == "") 
     { 
      this.Message = "Failed to connect to OPC server "+ serverName + 
          ": " + TranslateReturnCode()"; 
     } 
     else 
     { 
      this.Message = "Failed to connect to OPC server "+ serverName + 
          " on node " + nodeName + 
          ": " + TranslateReturnCode()"; 
     } 
    } 
} 

這對我來說似乎是一個完全合理的事情,但它不會編譯,因爲Message屬性是隻讀的。設置消息的唯一方法是將其傳遞給基類構造函數。爲什麼我不能在派生類的構造函數中設置它?我能想到的做任何類型的處理上爭論的唯一方法是創建一個靜態類構建消息:

public class OPCCaException : Exception 
{ 
    private static string BuildMessage(<some arguments>) 
    { 
     string message = "some message"; 
     return message; 
    } 
    public OPCCaException(ReturnCode returnCode, string serverName, string nodeName) : 
     base(BuildMessage(returnCode, serverName, nodeName)) 
    { 
    } 
} 

我不知道這是否會進行編譯。

這是做什麼的標準方法?

回答

8

public virtual string Message

Message是虛擬的 - 所以你可以很容易地覆蓋在你的班級。

public class OPCCaException : Exception 
{... 
    public override string Message 
    { 
    get { return "My fancy text";} 
    } 
} 

而且做的更標準的方式是通過電話來傳遞消息給基類構造函數:

public OPCCaException(...) : base(buildMessage(...)) 
{ 
} 
3

您可以將消息傳遞給基類構造函數,也可以忽略此消息你的課堂上的財產返還別的東西。例如:

public class OPCCaException : Exception 
{ 
    ReturnCode returnCode; 
    string serverName; 
    string nodeName; 

    public OPCCaException(ReturnCode returnCode, string serverName, string nodeName) 
     : base(); 
    { 
     this.returnCode = returnCode; 
     this.serverName = serverName; 
     this.nodeName = nodeName; 
    } 

    public override string Message 
    { 
     get 
     { 
      return string.Format("Failed to connect to OPC server {0}{1}: {2}", 
       serverName, 
       string.IsNullOrEmpty(nodeName ? "" : " on node " + nodeName), 
       TranslateReturnCode(returnCode) 
      ); 
     } 
    } 
} 
3

您是否注意到Exception.Message是虛擬財產?處理這種情況適當的方式將覆蓋Message,並提供自己的

public class MyException : Exception 
{ 
    private string myMessage = null; 
    public override string Message 
    { 
     get 
     { 
      return String.IsNullOrEmpty(myMessage) ? 
       base.Message : 
       myMessage; 
     } 
    } 

    public MyException(string message) : base() 
    { 
     myMessage = message; 
    } 
} 
+1

不,我沒有注意到消息是虛擬的。非常感謝所有你指出的人。很抱歉,我在這裏沒有足夠的聲譽來提高答案。 – 2013-03-07 20:44:29

4

爲什麼異常消息屬性只讀?

因爲異常意味着當它們沿着堆棧跟蹤行進時保持不動。如果在捕獲時想要提供更多信息/有意義的消息,則應將捕獲的異常包裝在另一個異常中。有一個constructor就是這樣做的。

這對我來說似乎是一件完全合理的事情,但它不會編譯,因爲Message屬性是隻讀的。

你想達到的是完全合理的。你試圖達到的方式不是。由於Message屬性是隻讀的,因此沒有人可以分配任何東西給它,包括你。出於這個原因,它變得虛擬。閱讀更多關於覆蓋MSDN的信息。

相關問題