5

おそらく、C# で最も不可解なのは、Exception クラスのメッセージ プロパティが読み取り専用であることです。この理由がわからないせいか、Exception から派生した妥当な例外クラスを作成しようとすると、イライラします。

たとえば (そして実際に私がやろうとしていること)、OPC サーバーに接続しようとしたときに発生させる例外を作成したいと考えています。試行が失敗すると OPCException 型のオブジェクトが発生しますが、ユーザーに詳細情報を提供したいと考えています。そこで、OPCCaException という名前のクラスを用意しました。このクラスは、元の例外からの戻りコード、サーバー名、およびホスト名の 3 つの引数を取ります。

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))
    {
    }
 }

それがコンパイルされるかどうかはわかりません。

これを行う標準的な方法は何ですか?

4

4 に答える 4

9

public virtual string Message

メッセージは仮想であるため、クラスで簡単にオーバーライドできます。

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

また、より標準的な方法は、基本クラスのコンストラクターへの呼び出しを介してメッセージを渡すことです。

public OPCCaException(...) : base(buildMessage(...))
{
}
于 2013-03-07T20:22:04.183 に答える
4

例外メッセージ プロパティが読み取り専用なのはなぜですか?

例外は、スタック トレースを移動するときにそのまま残るようになっているためです。キャプチャするときに、より多くの情報/意味のあるメッセージを提供したい場合は、キャプチャした例外を別の例外でラップする必要があります。まさにそれを行うコンストラクターがあります。

これは完全に合理的なことのように思えますが、Message プロパティが読み取り専用であるため、コンパイルできません。

あなたが達成しようとしていることは完全に合理的です。あなたが達成しようとしている方法はそうではありません。Message プロパティは読み取り専用であるため、あなたを含め、誰もそれに何かを割り当てることはできません。このため、仮想化されました。MSDNでのオーバーライドの詳細を参照してください。

于 2013-03-07T20:28:23.937 に答える
3

メッセージを基本クラスのコンストラクターに渡すか、クラスの Message プロパティをオーバーライドして別のものを返すことができます。例えば:

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)
             );
        }
    }
}
于 2013-03-07T20:23:56.200 に答える
2

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;
    }
}
于 2013-03-07T20:24:47.197 に答える