#896 – Custom Exceptions Should Be Marked as Serializable

Whenever you create a custom exception type, your exception type should always support serialization.  You do this using the Serializable attribute.  Exceptions should be serializable so that they can automatically be marshalled across application domains or threads.

At a minimum, you should mark your custom exception as serializable and implement the four basic constructors shown below.  (This example shows a custom exception type that has no custom data).

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

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

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

        protected DogBarkException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }

Note: For access to the SerializationInfo and StreamingContext types, you’ll need the following using statement:

using System.Runtime.Serialization;
Advertisement

#144 – Using Serialization to Implement Deep Copying

One alternative to using the ICloneable interface to support making a deep copy for a custom type is to use serialization.

This method will work only if the class to be copied, as well as all classes referenced by it (directly or indirectly), are serializable.

For example, if we have a Person class that has some value-typed members, but also a reference to an instance of the Address class, both the Person and Address classes have to be serializable in order to use this technique.

Here’s a generic method that makes a deep copy using serialization, serializing the object into a stream and then deserializing into a new object.

        public static T DeepCopy<T>(T obj)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
                stream.Position = 0;

                return (T)formatter.Deserialize(stream);
            }
        }

Using this method to deep copy a Person:

            Person bronteClone = DeepCopy<Person>(emily);