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
?
Yes, if you use constructors to create instances.
Is there no way to inherit constructors?
Nope.
Is there no way to encourage code reuse?
Well, I won't get into whether inheriting constructors would be a good or bad thing and whether it would encourage code reuse, since we don't have them and we're not going to get them. :-)
But here in 2014, with the current C#, you can get something very much like inherited constructors by using a generic create
method instead. It can be a useful tool to have in your belt, but you wouldn't reach for it lightly. I reached for it recently when faced with needing to pass something into the constructor of a base type used in a couple of hundred derived classes (until recently, the base didn't need any arguments, and so the default constructor was fine — the derived classes didn't declare constructors at all, and got the automatically-supplied one).
It looks like this:
// In Foo:
public T create<T>(int i) where: where T : Foo, new() {
T obj = new T();
// Do whatever you would do with `i` in `Foo(i)` here, for instance,
// if you save it as a data member; `obj.dataMember = i;`
return obj;
}
That says that you can call the generic create
function using a type parameter which is any subtype of Foo
that has a zero-arguments constructor.
Then, instead of doing Bar b new Bar(42)
, you'd do this:
var b = Foo.create<Bar>(42);
// or
Bar b = Foo.create<Bar>(42);
// or
var b = Bar.create<Bar>(42); // But you still need the <Bar> bit
// or
Bar b = Bar.create<Bar>(42);
There I've shown the create
method being on Foo
directly, but of course it could be in a factory class of some sort, if the information it's setting up can be set by that factory class.
Just for clarity: The name create
isn't important, it could be makeThingy
or whatever else you like.
Full Example
using System.IO;
using System;
class Program
{
static void Main()
{
Bar b1 = Foo.create<Bar>(42);
b1.ShowDataMember("b1");
Bar b2 = Bar.create<Bar>(43); // Just to show `Foo.create` vs. `Bar.create` doesn't matter
b2.ShowDataMember("b2");
}
class Foo
{
public int DataMember { get; private set; }
public static T create<T>(int i) where T: Foo, new()
{
T obj = new T();
obj.DataMember = i;
return obj;
}
}
class Bar : Foo
{
public void ShowDataMember(string prefix)
{
Console.WriteLine(prefix + ".DataMember = " + this.DataMember);
}
}
}