7

We have the following class hierarchy:

public class Base
{
    public Base()
    {
        // do generic initialization 
    }

    public Base(SomeClass param1) : this()
    {
        // init properties that require param1
    }

    public Base(SomeClass param1, OtherClass param2) : this(param1)
    {
        // init properties that require param2
    }

    // ...
}

public class Derived : Base
{
    public Derived()
    {
        // do custom initialization 
    }

    public Derived(SomeClass param1) : this() // ???
    {
        // do custom initialization using param1
    }

    public Derived(SomeClass param1, OtherClass param2) : this(param1) // ???
    {
        // do custom initialization using param2
    }

    // ...
}

We would require Derived to run both its own initialization routines, up the chain, and the corresponding ones from the base class. How do we chain the constructors without duplicating code/running some of the constructors twice?

Mihai
  • 2,835
  • 2
  • 28
  • 36

2 Answers2

5

In the derived class chain the constructors with the least parameters to the constructor with the most parameters, and then the derived constructor with the most parameters is chained to base. Something like this:

public class Base 
{
  public Base() : this(null, null)
  {
  }
  public Base(SomeClass param1) : this(param1, null)
  {
  }
  public Base(SomeClass param1, OtherClass param2)
  {
    if (param1 != null)
    {
      // initialise param1
    }
    if (param2 != null)
    {
      // initialise param2
    }
  }
}

public class Derived : Base
{
  public Derived() : this(null, null)
  {
  }
  public Derived(SomeClass param1) : this(param1, null)
  {
  }
  public Derived(SomeClass param1, OtherClass param2) : base(param1, param2)
  {
  }
} 

Depending on the context, it may be better to use default(T) instead of null to indicate a missing/default value.

Polyfun
  • 9,479
  • 4
  • 31
  • 39
  • @Mihai: To demonstrate it with strings, see my answer. It proves that all constructors are called. –  Aug 11 '11 at 15:56
3

You generally chain the constructor with least, to the one with most, like this:

public Derived(SomeClass param1) : this(param1, param2)
{}

See this article on Constructors in C# for more information.

Edit:

As per @Scott below:

The one with the most parameters would then would be public Derived(SomeClass param1, OtherClass param2) : base(param1, param2) and you put your initialization code in the 2 parameter constructor in the derived and the base

To demonstrate that all constructors are called, I drafted a program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    public class Base
    {
        public Base()
            : this(null, null)
        {
        }
        public Base(string param1)
            : this(param1, null)
        {
        }
        public Base(string param1, string param2)
        {
            Console.WriteLine("Base Class: " + param1 + "+" + param2);

            if (param1 != null)
            {
                // initialise param1
            }
            if (param2 != null)
            {
                // initialise param2
            }
        }
    }

    public class Derived : Base
    {
        public Derived()
            : this("", "")
        {
        }
        public Derived(string param1)
            : this(param1, "")
        {
        }
        public Derived(string param1, string param2)
            : base(param1, param2)
        {
            Console.WriteLine("Derived Class: " + param1 + "+" + param2);
        }
    } 
    class Program
    {
        static void Main(string[] args)
        {
            Derived d = new Derived("test1", "test2");
            Console.ReadLine();
        }
    }
}

Output:

Base class: test1+test2
Derived class: test1+test2
  • That wouldn't compile. Where does param2 come from? Also, you seem to be missing the fundamental problem. – siride Aug 11 '11 at 15:34
  • 2
    You would set it to the default of what you want if they called it. for example if they where both strings `public Derived(string param1) : this(param1, "")` – Scott Chamberlain Aug 11 '11 at 15:35
  • 2
    param2 is a literal, constant, static field, or other available value. – recursive Aug 11 '11 at 15:36
  • @siride: See here for the highest upvoted answer and how it is done: http://stackoverflow.com/questions/6944729/c-chain-calling-of-constructor –  Aug 11 '11 at 15:37
  • 1
    As Code Monkey says, in the derived class chain the constructors with the least parameters to the constructor with the most parameters, and then the derived constructor with the most parameters is chained to base. – Polyfun Aug 11 '11 at 15:38
  • 2
    @siride: to add on to @Code Monkey's comment, the one with the most paramaters would then would be `public Derived(SomeClass param1, OtherClass param2) : base(param1, param2)` and you put your initialization code in the 2 parameter constructor in the derived and the base. – Scott Chamberlain Aug 11 '11 at 15:39
  • @Code Monkey: yes, I understand that, but the problem is that the other base class constructors DON'T get called. It might be important that they do get called if the derived class is created with those same parameters. Chaining with `this()` to a single derived class constructor and then calling just one of the base class constructors is thus problematic. – siride Aug 11 '11 at 15:42
  • @siride: That's what base is for. –  Aug 11 '11 at 15:44
  • @Code Monkey: that wasn't in your original post. Your edit sounds reasonable, except for the fact that the other two base constructors are never called from derived. – siride Aug 11 '11 at 15:48