How to inherit constructors?

189,560

Solution 1

Yes, you will have to implement the constructors that make sense for each derivation and then use the base keyword to direct that constructor to the appropriate base class or the this keyword to direct a constructor to another constructor in the same class.

If the compiler made assumptions about inheriting constructors, we wouldn't be able to properly determine how our objects were instantiated. In the most part, you should consider why you have so many constructors and consider reducing them to only one or two in the base class. The derived classes can then mask out some of them using constant values like null and only expose the necessary ones through their constructors.

Update

In C#4 you could specify default parameter values and use named parameters to make a single constructor support multiple argument configurations rather than having one constructor per configuration.

Solution 2

387 constructors?? That's your main problem. How about this instead?

public Foo(params int[] list) {...}

Solution 3

Yes, you have to copy all 387 constructors. You can do some reuse by redirecting them:

  public Bar(int i): base(i) {}
  public Bar(int i, int j) : base(i, j) {}

but that's the best you can do.

Solution 4

Too bad we're kind of forced to tell the compiler the obvious:

Subclass(): base() {}
Subclass(int x): base(x) {}
Subclass(int x,y): base(x,y) {}

I only need to do 3 constructors in 12 subclasses, so it's no big deal, but I'm not too fond of repeating that on every subclass, after being used to not having to write it for so long. I'm sure there's a valid reason for it, but I don't think I've ever encountered a problem that requires this kind of restriction.

Solution 5

Don't forget that you can also redirect constructors to other constructors at the same level of inheritance:

public Bar(int i, int j) : this(i) { ... }
                            ^^^^^
Share:
189,560

Related videos on Youtube

mistertodd
Author by

mistertodd

Any code is public domain. No attribution required. జ్ఞా <sup>🕗</sup>🕗 Yes, i do write i with a lowercase i. The Meta Stackexchange answer that I am most proud of

Updated on November 03, 2020

Comments

  • mistertodd
    mistertodd over 3 years

    Imagine a base class with many constructors and a virtual method

    public class Foo
    {
       ...
       public Foo() {...}
       public Foo(int i) {...}
       ...
       public virtual void SomethingElse() {...}
       ...
    }
    

    and now i want to create a descendant class that overrides the virtual method:

    public class Bar : Foo 
    {
       public override void SomethingElse() {...}
    }
    

    And another descendant that does some more stuff:

    public class Bah : Bar
    {
       public void DoMoreStuff() {...}
    }
    

    Do i really have to copy all constructors from Foo into Bar and Bah? And then if i change a constructor signature in Foo, do i have to update it in Bar and Bah?

    Is there no way to inherit constructors? Is there no way to encourage code reuse?

  • Kon
    Kon over 15 years
    To be honest, I've never used them myself in any production code. I usually have List<int> or some collection I pass. I long for the day where I get to leverage params. :)
  • Chris Marasti-Georg
    Chris Marasti-Georg over 15 years
    You shouldn't call virtual methods in constructors - a subclass will not have run its constructor at the time the virtual method is called.
  • mistertodd
    mistertodd over 15 years
    i think having to copy the signature of one constructor is too many. In my real situation i had one constructor, and i do not want to have to copy it. Then i have to change it in two places.
  • Jeff Yates
    Jeff Yates over 15 years
    This is why upfront design is important. You shouldn't be coding with 100% conviction that it all has to change.
  • C. Dragon 76
    C. Dragon 76 over 15 years
    Yes, that's probably good advice. You could have the virtual Initialize pattern be called by callers after construction though. The pattern would be Bar bar = new Bar(); bar.Initialize();
  • trampster
    trampster over 15 years
    If you require your class to be immutable then you don't want to expose properties. Because then your class has state.
  • trampster
    trampster over 15 years
    Not addressing the real question. And doesn't help if class needs immutable state.
  • Chris Marasti-Georg
    Chris Marasti-Georg over 15 years
    Hence the "unless you have a good reason". The point is, any class with 387 constructors does too much.
  • mistertodd
    mistertodd over 15 years
    Does your answer change if there was just one constructor?
  • mistertodd
    mistertodd over 15 years
    This sounds interesting, although i don't know what covariant means. :(
  • mistertodd
    mistertodd over 15 years
    Yes, that is a very good idea; although i would probably have initialize a static method that returns a class
  • Callum Rogers
    Callum Rogers almost 14 years
    Resharper makes this easy! (Alt+Insert, Constructors)
  • Admin
    Admin over 12 years
    Basically, it means that you can override a function with the same parameters by changing its return type, so "string Function(int,int)" can be different from "int Function(int,int)". If you try this in C# now, it complains that the overload already exists.
  • mistertodd
    mistertodd almost 12 years
    The question is unchanged if i have 2 constructors; how to solve the problem of having to copy-and-paste 2 lines.
  • too
    too over 11 years
    Invisible base class constructors are a result of choices made by designers of C# language (and quite possibly other CLR languages). That being sad it has nothing to do with upfront design of application but with limitations of language which renders design with many constructors in base class (often) impracticable.
  • Jeff Yates
    Jeff Yates over 11 years
    I disagree. Upfront design is still responsible, regardless of language limitations. You have to design for the platform you are implementing on and the language you are using.
  • too
    too over 11 years
    In such context you're right although now "best practices" becomes "best available practices".
  • Basic
    Basic almost 11 years
    The most annoying one for me is custom exceptions - Sub New(), Sub New(Message As String), Sub New(Message As String, InnerEx as Exception), Sub New(Info As Serialization.SerializationInfo, Context As Serialization.StreamingContext)... Yawn `
  • supercat
    supercat over 10 years
    The issue isn't one of visibility. A child-class constructor cannot be used for building a derived-class object except when called from the derived class constructor. What is needed IMHO is a facility by which a child class can specify that for all parent-class constructors the compiler should auto-generate a child-class constructor with the same parameters, which calls the appropriate parent constructor and then a general-purpose child-class constructor template.
  • Matt Burland
    Matt Burland about 10 years
    @Basic: It maybe annoying (okay, it is), but you don't have to implement all of them. Only the ones you expect to actually use.
  • Basic
    Basic about 10 years
    @MattBurland It depends on whether or not your exceptions will be seen by other code. If so, you need to cover them all in case it attempts to serialize/instantiate and makes assumptions. I admit I only do it to make the code feel "right" and at least some of the time it's not required.
  • Slipp D. Thompson
    Slipp D. Thompson over 9 years
    “specify default parameter values and use named parameters to make a single constructor support multiple argument configurations” Would you be able to provide a simple example of this? I'm not quite getting what parts of this go in the parent class and what goes in the child class, and how they work together.
  • James Curran
    James Curran almost 8 years
    That really only works if the parameters are the same type, and are used as a list to initialize the object. But if the constructors had even different signature (say one takes two ints, and another two string, and another and int and a string, and a fourth, an float and an enum. You'd be spending most of the constructor checking types and unbox -- doing things at run-time that really should be done by the compiler.
  • Mark K Cowan
    Mark K Cowan over 7 years
    This is one area where newer C++ really shines against easier languages :)
  • Mark K Cowan
    Mark K Cowan over 7 years
    I was just about to post a template factory function solution... But then you beat me to it by 2.5 years
  • Dennis Gorelik
    Dennis Gorelik almost 7 years
    Single constructor still has to be copy-pasted into all derived classes and that sucks.
  • Triynko
    Triynko over 5 years
    Yeah, wth. C++ 11 supports compiler option to inherit constructors automatically, instead of making us type empty copies of them. Come on C#! This is a nghtmare to update in subclasses in multiple domains every time we need to add a new optional parameter.
  • Triynko
    Triynko over 5 years
    Apparently, this compiler option exists in C++ 11, but C# has fallen behind.