Search code examples
c#.netbinary-serialization

Can extracting a base class break binary serialisation


If I have a class with a number of fields, and I serialise it using binary serialisation.

I then extract a base class and move some of the fields from the class into the base class. Eg.

class Class
{
     int field1;
     string field2;
}

Is changed to

class Class : BaseClass
{
     int field1;
}

class BaseClass
{
     string field2;
}

Is it possible for this to break serialisation in any way - i.e. will it always be possible to deserialise old versions of Class into new versions of Class and vice versa.

Experiments I performed indicated that this is fine, but if somebody knows of any edge cases where this wouldn't work, that would obviously be great before I put this into production code.


Solution

  • EDIT: There is a problem while deserializing: the member "field1" will not be properly deserialized.

    1) Serialized person:

    var person = new Employee()
                { 
                    Name = "Mark Zuckerberg",
                    Salary = 1000
                };
    
    var bf = new BinaryFormatter();
    bf.Serialize(new FileStream("C:\\TEMP\\test.dat", FileMode.Create), person);
    
    
    [Serializable]
    public class Employee
    {
      public string Name { get; set; }
      public decimal Salary { get; set; }
    }
    

    2) Changed class structure

    [Serializable]
    public abstract class Person
    {
      public string Name { get; set; }           
    }
    
    [Serializable]
    public class Employee : Person
    {            
      public decimal Salary { get; set; }
    }
    

    3) Deserialized: Name is null enter image description here


    Original Answer:

    Assuming you are using the BinaryFormatter, this article does not mention anything about it, so I guess it's fine (EDIT: It's NOT fine).

    Here are some best practices to follow generally (also extracted from above article):

    • Never remove a serialized field.
    • Never apply the NonSerializedAttribute attribute to a field if the attribute was not applied to the field in the previous version.
    • Never change the name or the type of a serialized field.
    • When adding a new serialized field, apply the OptionalFieldAttribute attribute.
    • When removing a NonSerializedAttribute attribute from a field (that was not serializable in a previous version), apply the OptionalFieldAttribute attribute.
    • For all optional fields, set meaningful defaults using the serialization callbacks unless 0 or null as defaults are acceptable.

    To ensure that a type will be compatible with future serialization engines, follow these guidelines:

    • Always set the VersionAdded property on the OptionalFieldAttribute attribute correctly.
    • Avoid branched versioning.