1

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.

Yair Halberstadt
  • 5,733
  • 28
  • 60

1 Answers1

1

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.
Fabian Bigler
  • 10,403
  • 6
  • 47
  • 70
  • 1
    Hmmm.Can you think of any way to fix that problem? – Yair Halberstadt Oct 25 '18 at 22:29
  • @YairHalberstadt Not a proper solution, I'm afraid. The obvious option which comes into my mind is maintaining the old model until the data has been migrated and then discard it.In your deserializing code you could check if Name is null, use the old Model to deserialize and then assign that object to the new one. – Fabian Bigler Oct 26 '18 at 06:06