NullReferenceExeption in C# when the container is initialized

In the code listed below, I get a "NullReferenceExeption" with the error : "Object reference not set to an instance of an object". I am completely new to C#, but guess the error is related to the inheritance and/or the template definitions. The list gets initialized, and when debugging I can confirm that the list does not point to NULL. I can't figure out how to do this in another way - Appreciate the help! (Sorry about the confusing class names / structure) EDIT : The exeption happens here : this.localSMT.doSomething(base.list);

  public class VTEST<V>
{
    public List<V> list;
    public LocalSMT<V> localSMT;
    public VTEST()
    {
        list = new List<V>();
    }
}
public class VTEST_FSUB<V> : VTEST<V>
{
    public VTEST_FSUB()
    {
        do_virtual();
    }
    public void do_virtual()
    {
        this.localSMT.doSomething(base.list);
    }
}
public class VTEST_RUN : VTEST_FSUB<int>
{
    public VTEST_RUN()
    {
        localSMT = new VTEST_SUB();
    }
}

public class LocalSMT<V>
{
    public LocalSMT() { }
    public virtual void doSomething(List<V> value) { }
}
public class VTEST_SUB : LocalSMT<int>
{
    public VTEST_SUB(){}
    public override void doSomething(List<int> value) { 
            System.Console.WriteLine("VTEST_SUB VIRTUAL");
    }
}
class Program 
{

    Program() {}

    static void Main(string[] args)
    {
        VTEST_RUN run = new VTEST_RUN();
    }
}
Jon Skeet
people
quotationmark

The problem is that the VTEST_FSUB<V> constructor body is executing before the VTEST_RUN constructor body. So when do_virtual is called, localSMT is still null. Then do_virtual tries to call a method on localSMT, hence the exception.

Basically the initialization order for any class in the hierarchy is:

  • Initialize variables which have been declared within an initializer at the point of declaration (any other variables just have the variable type's default value)
  • Chain up to the base class initialization
  • Execute the constructor body

See my article on constructor chaining for more details.

Lessons to learn:

  • Avoid public fields. If you use private fields, it's easy to find every piece of code that reads them and writes to them
  • Ideally, use readonly fields: if you'd passed the value up the constructor chain and set it in the VTEST<V> constructor, you wouldn't have had a problem. (Admittedly readonly fields can still be a pain because of the next point...)
  • Avoid virtual method calls in constructors. In this case that wasn't the problem, but you could easily have had the same issue if do_virtual had been abstract in VTEST_FSUB<V> and overridden to call localSMT.doSomething in VTEST_RUN. It would still have executed before the constructor body had run, which would be surprising. Anything you call within a constructor is operating on a partially-initialized object, which is a precarious situation.
  • Avoid large inheritance hierarchies. They're a pain to work with and reason about.
  • Follow .NET naming conventions! Your code is partly hard to read because it's so unidiomatic. Even when you're just giving sample code, at least follow the capitalization conventions.

people

See more on this question at Stackoverflow