How to inherit constructors?
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) { ... }
^^^^^
Related videos on Youtube
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, 2020Comments
-
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 over 15 yearsTo 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 over 15 yearsYou shouldn't call virtual methods in constructors - a subclass will not have run its constructor at the time the virtual method is called.
-
mistertodd over 15 yearsi 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 over 15 yearsThis is why upfront design is important. You shouldn't be coding with 100% conviction that it all has to change.
-
C. Dragon 76 over 15 yearsYes, 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 over 15 yearsIf you require your class to be immutable then you don't want to expose properties. Because then your class has state.
-
trampster over 15 yearsNot addressing the real question. And doesn't help if class needs immutable state.
-
Chris Marasti-Georg over 15 yearsHence the "unless you have a good reason". The point is, any class with 387 constructors does too much.
-
mistertodd over 15 yearsDoes your answer change if there was just one constructor?
-
mistertodd over 15 yearsThis sounds interesting, although i don't know what covariant means. :(
-
mistertodd over 15 yearsYes, that is a very good idea; although i would probably have initialize a static method that returns a class
-
Callum Rogers almost 14 yearsResharper makes this easy! (Alt+Insert, Constructors)
-
Admin over 12 yearsBasically, 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 almost 12 yearsThe question is unchanged if i have 2 constructors; how to solve the problem of having to copy-and-paste 2 lines.
-
too over 11 yearsInvisible 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 over 11 yearsI 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 over 11 yearsIn such context you're right although now "best practices" becomes "best available practices".
-
Basic almost 11 yearsThe 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 over 10 yearsThe 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 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 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 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 almost 8 yearsThat 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 over 7 yearsThis is one area where newer C++ really shines against easier languages :)
-
Mark K Cowan over 7 yearsI was just about to post a template factory function solution... But then you beat me to it by 2.5 years
-
Dennis Gorelik almost 7 yearsSingle constructor still has to be copy-pasted into all derived classes and that sucks.
-
Triynko over 5 yearsYeah, 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 over 5 yearsApparently, this compiler option exists in C++ 11, but C# has fallen behind.