[Serializable] and ISerializable

Eagle-eyed readers will have noticed that in all the preceding examples the classes are sealed. This is no accident. Marking a class as [Serializable] and deciding whether to implement ISerializable has some specific implications for both base and derived types, and deserves separate discussion.

Consider the following serializable class hierarchy:

[Serializable]
public class Person {
  public string Name;
  public int Age;
  // Rest of class...
}
  
[Serializable]
public sealed class Student: Person {
  public string Course;
  // Rest of class...
}

In this example both Person and Student are serializable, and both classes use the default runtime serialization behavior since neither class implements ISerializable.

Now imagine that the developer of Person decides for some reason to implement ISerializable and provide a deserialization constructor to control Person serialization. The new version of Person might look like this:

[Serializable]
public class Person : ISerialization {
  public string Name;
  public int Age;
  public void GetObjectData(SerializationInfo si, StreamingContext sc) {
    si.AddValue("IChangedTheNameFieldName", Name);
    si.AddValue("IChangedTheAgeFieldName", Age);
  }
  protected Person(SerializationInfo si, StreamingContext sc)  {
    Name = si.GetString("IChangedTheNameFieldName");
    Age = sc.GetInt32("IChangedTheAgeFieldName");
  }
  // Rest of class...
}

Although this works for instances of Person, this change breaks serialization of Student instances. Serializing a ...

Get C# in a Nutshell, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.