The answer to What is the correct way to make exceptions serializable? says that the "correct" base implementation for a custom exception includes 4 ctors:
[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)
{
}
}
Right off the bat, I'd say that's a really bad name for an Exception type. But, beyond that,
For purposes of binary serialization, which is what the SO question was referring to, must I implement all 4 constructors? I think for purposes of [Serializable], I must provide a ctor that accepts 2 args of type (SerializationInfo, StreamingContext), because the exception derives from System.Exception, which itself does custom serialization. I can understand that. But must I implement the other ctors, in order to properly provide a serializable exception? I know that if I want to allow a type to be xml-serializable, I need to provide the default (no-op) ctor. Is the same true for [Serializable]? For a moment, let's confine ourselves to the narrow concern of [Serializable], and leave aside any broader guidelines regarding "framework design".
Moving to the broader question: The guidelines say that custom exceptions should implement the 4 common ctors. What is the reasoning behind this guideline? If I design a custom exception, is it really bad manners, or even a bug, if I don't provide a null/default ctor? Is it really bad manners, or even a bug, if I don't provide a ctor that allows an innerException? Why? Consider the case that my custom exception is generated within my library code, and the only instances I ever throw include a message, and no innerException.
In short, is the following code acceptable for a custom exception that provides no additional properties?
[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) { }
}
see also: Winterdom blog: Make exceptions Serializable.