88

I know it's not possible to inherit constructors in C#, but there's probably a way to do what I want to do.

I have a base class that is inherited by many other classes, and it has an Init method that does some initializing taking 1 parameter. All other inheriting classes also need this initializing, but I'd need to create separate constructors for all of them that would like like this:

public Constructor(Parameter p) {
    base.Init(p);
}

That totally violates the DRY principles! How can I have all necessary stuff initialized without creating dozens of constructors?

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Alex
  • 34,581
  • 26
  • 91
  • 135
  • 4
    Worse than violating DRY principles is violating the invariant principle. `Init` as the name of a method is generally a strong sign that objects are needlessly existing in invalid states where the only thing they are good for is causing bugs. – Jon Hanna Oct 06 '10 at 14:29
  • 4
    C# in doesn't really follow DRY at all.  This may be bothersome but… honestly, you can't tell me you're not tired of typing `public`, `protected`, and `private` over and over and over? – Slipp D. Thompson Sep 24 '14 at 20:00
  • 1
    @SlippD.Thompson: That's another area where C++ is actually *less* wordy than easier languages... The previous one I just saw was regarding exposing base constructors in a derived class. – Mark K Cowan Dec 21 '16 at 13:45
  • 2
    @SlippD.Thompson Every time you type `public`, etc., you're specifying a new piece of knowledge. Therefore, it doesn't violate DRY. – MarredCheese Jul 27 '21 at 03:14

6 Answers6

135

You don't need to create loads of constructors, all with the same code; you create only one, but have the derived classes call the base constructor:

public class Base
{
    public Base(Parameter p)
    {
        Init(p)
    }

    void Init(Parameter p)
    {
        // common initialisation code
    }
}

public class Derived : Base
{
    public Derived(Parameter p) : base(p)
    {
 
    }
}
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Rob Levine
  • 40,328
  • 13
  • 85
  • 111
  • 1
    That's what I need. Although I will have to create constructors for classes that don't have them, I won't have to repeat the code. – Alex Oct 06 '10 at 14:20
  • 43
    I wish C# had something like C++'s inheriting constructors, it's still annoying to call all the base constructors –  May 19 '16 at 10:33
  • 5
    Constant double handling of constructors is pretty annoying... so I went googling as to why. After reading the discussion here I feel less upset about it. There are some good reasons they didn't do it. https://social.msdn.microsoft.com/forums/en-US/6c860066-9dd5-4689-acc9-b8d0b4c98e00/why-c-constructors-cannot-be-inherited – Damien Sawyer Feb 23 '19 at 21:16
  • At this point, if you have such a simple constructor, it's more cumbersome to use inheritance than just creating brand new ones for each of your classes. – Szesan Feb 22 '21 at 17:26
21

Change the init function so it is the constructor for the base class, and then call it from the inherited objects like this:

public InheritedObject(Parameter p) : base(p)
{
}

The base constructor will be invoked before any code in the constructor itself runs.

AHM
  • 5,145
  • 34
  • 37
9

The only way to not repeat the base.Init call is to instead call the base constructor

class Base
{
  public Base(Parameter p)
  {
    this.Init(p)
  }

  private void Init(Parameter p)
  {
      ...
  }
}

class Inherited : Base
{
   public Inherited(Parameter p)
     : base(p)
   {
      // other constructor logic, but Init is already called.
   }
}
Jamiec
  • 133,658
  • 13
  • 134
  • 193
5

You can't inherit constructors but you can call them from your derived children's constructors. If you make the base classes default constructor private it will force you to select a base constructor every time you create a derived class.

class A
{
    protected A(int x)
    {

    }
}
class B : A
{
    B(int x)
        : base(x)
    {

    }
}
rerun
  • 25,014
  • 6
  • 48
  • 78
3

Something like this?

public Constructor(Parameter p) : base(p) {

}

And the base class:

public Base(Parameter p)
{
    Init(p);
}

You can even mark your Init method as virtual, so you can do some sweet override in your other classes, if need be! ;)

public virtual void Init() { }

and in your other classes:

public override void Init() { base.Init(); //Do other stuff }
Arcturus
  • 26,677
  • 10
  • 92
  • 107
  • 3
    Although you have to be very careful calling a virtual method from a constructor - the subclass' constructor will not have run when the overridden method gets called by the superclass, so member variables etc would not have been initialized. – thecoop Oct 06 '10 at 14:14
  • 2
    The virtual init method seems pointless, though. Normaly you should avoid doing work in constructors, and only use them for initialization, and if it is only initializing, then why not just use the constructor? – AHM Oct 06 '10 at 17:14
0

The methods in the base class are automatically available in the derived class. All that is needed is to describe them as protected or public. Their signature does not need to be repeated in the derived class.

If the base class does not want them available, they will be marked private.

Since the constructors are missing this choice, this looks to be a deficiency in the C# language. Perhaps the language designers are unable to solve.

David Pierson
  • 182
  • 2
  • 9