2013-03-07 84 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的信息。

相关问题