Deserialization mythbuster

I had always thought that when an object got deserialized (using the default serialization support), the basic process was:

  1. A new object is created using the object’s default constructor
  2. The object’s properties are populated via reflection from the object’s serialized stream

Turns out that’s not true – the constructor is never called! This was a problem for me as I was initializing my NonSerialized variables in the constructor, but after the object was Deserialized and I tried to access them, I was getting a NullReferenceException:


[Serializable]
public class Person {
    private string name;
    [NonSerialized] private IList friends;

    public string Name {
        get { return name; }
        set { name = value; }
    }

    public void AddFriend(string name) {
        friends.Add(name);    // throws NRE after deserialization
    }

    public Person() {
        friends = new List();
    }
}

Turns out that the correct way of doing something like this is to use the OnDeserialized attribute on an initialization method. The attribute requires that the method signature takes a single parameter – a StreamingContext:


[Serializable]
public class Person {
    private string name;
    [NonSerialized] private IList friends;

    public string Name {
        get { return name; }
        set { name = value; }
    }

    public void AddFriend(string name) {
        friends.Add(name);    // no more NRE after deserialization
    }

    [OnDeserialized]
    private void Init(StreamingContext context) {
        friends = new List();
    }

    public Person() {
        Init(new StreamingContext());
    }
}

I’m not sure if this is technically the best way of achieving this, but it works, and besides creating an empty StreamingContext in the constructor (StreamingContext is a struct so you can’t use null), it feels ok to me. Any thoughts?

Posted in .Net, C# by Gerrod at December 14th, 2006.

One Response to “Deserialization mythbuster”

  1. Andrew says:

    You could overload the Init(StreamingContext) method with a non-parameterised Init() method and create the List instance there. Call the Init() method from the constructor as well as from Init(StreamingContext). Then you would not have to create the anonymous StreamingContext instance in the constructor.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Quickduck logo