66

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
  • 20,623
  • 15
  • 71
  • 98
Alex
  • 30,475
  • 22
  • 84
  • 129
  • 3
    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
  • 3
    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

5 Answers5

110

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
  • 18,294
  • 21
  • 100
  • 129
Rob Levine
  • 37,567
  • 13
  • 78
  • 108
  • 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
  • 26
    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
  • 4
    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
15

Change the init function to 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
  • 4,737
  • 30
  • 36
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
  • 118,012
  • 12
  • 125
  • 175
4

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
  • 23,827
  • 6
  • 44
  • 74
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
  • 25,273
  • 10
  • 88
  • 101
  • 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