例外をシリアル化できるようにする正しい方法は何ですか?カスタム例外の「正しい」基本実装には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)
{
}
}
すぐに、それは例外タイプの本当に悪い名前だと思います。しかし、それを超えて、
SOの質問が参照していたバイナリシリアル化の目的で、4つのコンストラクターすべてを実装する必要がありますか?[Serializable]の目的のために、タイプ(SerializationInfo、StreamingContext)の2つの引数を受け入れるctorを提供する必要があると思います。これは、例外がSystem.Exceptionから派生し、それ自体がカスタムシリアル化を行うためです。理解できます。しかし、シリアル化可能な例外を適切に提供するために、他のctorを実装する必要がありますか?型をxmlシリアル化できるようにする場合は、デフォルトの(no-op)コンストラクターを提供する必要があることを知っています。[Serializable]についても同じですか?しばらくの間、[Serializable]の狭い関心事に限定し、「フレームワーク設計」に関するより広いガイドラインは脇に置いておきましょう。
より広い質問に移ります:ガイドラインは、カスタム例外は4つの一般的なctorを実装する必要があると述べています。このガイドラインの背後にある理由は何ですか?カスタム例外を設計する場合、null /デフォルトのコンストラクターを提供しないと、それは本当に悪いマナーですか、それともバグですか?innerExceptionを許可するctorを提供しない場合、それは本当に悪いマナーですか、それともバグですか?なんで?カスタム例外がライブラリコード内で生成され、スローするインスタンスにはメッセージが含まれ、innerExceptionは含まれない場合を考えてみます。
つまり、次のコードは、追加のプロパティを提供しないカスタム例外に受け入れられますか?
[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ブログ:例外をシリアル化可能にします。