Static initialization goof-up

I am writing this blog entry as a reminder to myself to be careful when using static fields or properties, and I wanted to document some silliness on my part for posterity. Recently I was working on some code where I wanted to keep track of derived class instances by storing them in a static list in the base class. The classes I was working on were non-trivial and fairly complex (and the original versions were not even authored by me). So for the sake of this blog entry, I’ve come up with simplified base and derived classes to explain what happened. Here’s what the base class looked like :

class Base
{
    private static List list = new List();

    public static List List
    {
        get { return Base.list; }
    }

    private Base()
    {
        Base.list.Add(this);
    }

    public string Name { get; private set; }

    public Base(string name) : this()
    {
        this.Name = name;
    }
}

And here’s what a typical derived class would be like :

class Derived : Base
{
    public static Derived Nish = new Derived("Nish");
    public static Derived Andrew = new Derived("Andrew");
    public static Derived Megan = new Derived("Megan");

    public Derived(string name) : base(name)
    {
    }
}

I thought it was all good, and then ran some code that did an iteration of the list :

foreach (Base item in Derived.List)
{
    Console.WriteLine(item.Name);
}

To my tremendous surprise nothing came up and the list was empty. For a full 10 minutes, the idiot that I am, I kept pondering over this and wondering what the heck was going on. Then it hit me just like that. Even though I was accessing Derived.List, that was just a C# syntactic convenience that allowed me to write it that way because Derived did not have a List member at all (the compiler auto-fixes this to Base.List in the generated MSIL). The property was defined on Base, and thus Derived has not been accessed yet when I iterate Derived.List. So Derived‘s static initialization has not even happened yet. Once I realized my folly, fixing it was straight forward, I had to bring down the List property to the Derived class. This meant that every derived class had to do that which was a bit of an annoyance but not so much as to be a show stopper. Here’s the correct code (for my simplified example) :

class Base
{
    protected static List list = new List();

    private Base()
    {
        Base.list.Add(this);
    }

    public string Name { get; private set; }

    public Base(string name) : this()
    {
        this.Name = name;
    }
}

class Derived : Base
{
    public static Derived Nish = new Derived("Nish");
    public static Derived Andrew = new Derived("Andrew");
    public static Derived Megan = new Derived("Megan");

    public Derived(string name) : base(name)
    {
    }

    public static List List
    {
        get { return Base.list; }
    }
}

Next time you are using static properties in your base classes, just be a little careful – I know I’ll be.

Advertisements

2 thoughts on “Static initialization goof-up

  1. I think this syntactic sugar is not necessary at all. Here, it made you initially assume that Derived has been accessed. Whether it is in an application code or in the language itself, unnecessary means mostly harmful to me.

    The lesson one should learn her should be to not to eat the sugar. Which would remind you that Derived needs a static constructor or another empty static loader method to be called, instead of an unnecessary property which does not reflect its purpose.

    BTW, You could use a public readonly (initonly in C++ as you probably know) field in the base class, if you are not going to return a copy. Of course, anything I wrote above, might be irrelevant since I know things get lost during simplifying a piece of code.

  2. hi I have read ur article
    The singular non-modality of MFC modal dialogs
    It is really gud one buddy and adds to my knowledge and moreover ur use if chitpping birds reallyy coooooooooooool
    i just want to add if we post any message from modal dialog to its parent at that point of time also modal property of dialogs vanish.
    kindly correct me if im wrong

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s