Is there any way to pass "this" to the base constructor?
abstract class Base<TSelf>
{
public ICollection<TSelf> List;
public Base(ICollection<TSelf> list, TSelf self)
{
List = list;
List.Add(self);
}
}
class Implementation : Base<Implementation>
{
public Implementation() : base(new List<Implementation>(), this)
{
}
}
Obviously there is a compilation error in the constructor of Implementation
where this
is passed to base
.
I also do not see any way to instantiate list
at Base
level.
No, you can't use this
in a constructor initializer. You'd have to add call Add(this)
afterwards - but you can do that in the Base<TSelf>
constructor, so long as you cast to TSelf
. You need to cast this
to object
first before casting to TSelf
for fairly complicated reasons around the conversions allowed with type parameters, unfortunately.
You can create a List<TSelf>
in the Base
constructor though, with no problem. Here's sample code showing both of these:
abstract class Base<TSelf>
{
// Let's make it a property rather than a public field...
public ICollection<TSelf> List { get; }
public Base()
{
List = new List<TSelf>();
// This will obviously fail if you try to create a `Base<Foo>`
// from a class that isn't a Foo
TSelf selfThis = (TSelf) (object) this;
List.Add(selfThis);
}
}
class Implementation : Base<Implementation>
{
}
You can add a constraint to TSelf
to make the casting failure less likely accidentally but not impossible:
abstract class Base<TSelf> where TSelf : Base<TSelf>
That doesn't stop you from writing
class Implementation : Base<Implementation> {}
class Evil : Base<Implementation> {}
Then when you construct an instance of Evil
, you're trying to add an Evil
reference to a List<Implementation>
which can't work... and the cast fails to stop you from getting that far.
See more on this question at Stackoverflow