2

例外をシリアル化できるようにする正しい方法は何ですか?カスタム例外の「正しい」基本実装には4つのctorが含まれていると言います。

[Serializable]
public class SerializableExceptionWithoutCustomProperties : Exception
{
    public SerializableExceptionWithoutCustomProperties()
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message) 
        : base(message)
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message, Exception innerException) 
        : base(message, innerException)
    {
    }

    // Without this constructor, deserialization will fail
    protected SerializableExceptionWithoutCustomProperties(SerializationInfo info, StreamingContext context) 
        : base(info, context)
    {
    }
}

すぐに、それは例外タイプの本当に悪い名前だと思います。しかし、それを超えて、

  1. SOの質問が参照していたバイナリシリアル化の目的で、4つのコンストラクターすべてを実装する必要がありますか?[Serializable]の目的のために、タイプ(SerializationInfo、StreamingContext)の2つの引数を受け入れるctorを提供する必要があると思います。これは、例外がSystem.Exceptionから派生し、それ自体がカスタムシリアル化を行うためです。理解できます。しかし、シリアル化可能な例外を適切に提供するために、他のctorを実装する必要がありますか?型をxmlシリアル化できるようにする場合は、デフォルトの(no-op)コンストラクターを提供する必要があることを知っています。[Serializable]についても同じですか?しばらくの間、[Serializable]の狭い関心事に限定し、「フレームワーク設計」に関するより広いガイドラインは脇に置いておきましょう。

  2. より広い質問に移ります:ガイドラインはカスタム例外は4つの一般的なctorを実装する必要があると述べています。このガイドラインの背後にある理由は何ですか?カスタム例外を設計する場合、null /デフォルトのコンストラクターを提供しないと、それは本当に悪いマナーですか、それともバグですか?innerExceptionを許可するctorを提供しない場合、それは本当に悪いマナーですか、それともバグですか?なんで?カスタム例外がライブラリコード内で生成され、スローするインスタンスにはメッセージが含まれ、innerExceptionは含まれない場合を考えてみます。

  3. つまり、次のコードは、追加のプロパティを提供しないカスタム例外に受け入れられますか?


[Serializable]
public class CustomException : Exception
{
    public CustomException(string message) : base(message) { }

    // Without this constructor, deserialization will fail
    protected CustomException(SerializationInfo info, StreamingContext context) 
        : base(info, context) { }
}

参照:Winterdomブログ:例外をシリアル化可能にします。

4

4 に答える 4

2

関連するコード分析の警告は CA1032 であり、参照ページにはこの理由が示されています。

コンストラクターの完全なセットを提供しないと、例外を正しく処理することが難しくなる可能性があります。たとえば、署名 NewException(string, Exception) を持つコンストラクターは、他の例外によって引き起こされる例外を作成するために使用されます。このコンストラクターがないと、内部 (ネストされた) 例外を含むカスタム例外のインスタンスを作成してスローすることはできません。これは、このような状況でマネージ コードが行うべきことです。最初の 3 つの例外コンストラクターは、慣例により public です。4 番目のコンストラクターは、封印されていないクラスでは保護され、封印されたクラスではプライベートです。

あなたの状況が例外を正当化するかどうかを判断できるのは、あなたまたはあなたのプロジェクト チームだけです (申し訳ありません...)

于 2009-07-01T12:24:56.930 に答える
1

ねえ、私はそれが少なくともマイクロソフトによってアドバイスされていることを知っています。VS2008(または以前のバージョン)を使用している場合は、次のように入力することで、VisualStudioに簡単に作成させることができます。

exception

エディターでTabキーを押します(2回?)。これによりそれらが作成され、クラスに新しい名前を付ける機会が与えられます。

于 2009-07-01T12:27:07.910 に答える
1

どの回答も気に入りませんでした。私は、デフォルトのコンストラクターとネストされたコンストラクターを含む、カスタム例外で「通常の」コンストラクターを削除できるという、提案されたソリューションに落ち着いています。また、アプリドメイン間の呼び出しのため、シリアル化が機能することを確認する必要があります。

于 2009-07-08T03:20:33.797 に答える
0

提案: 他の人があなたの例外を使用する場合、これらの他の人は .NET 例外に精通しているため、ガイドラインに従わないのはなぜですか? これらは、.NET Framework で使用されるものと同じです。

定義しているカスタム例外タイプの数を考えると、これは大変な作業だと感じていますか? その場合、これは、多数のカスタム例外を作成しないように指定するガイドラインに従うもう 1 つの理由になります。

于 2009-07-01T12:21:57.967 に答える