Passing "this" to base constructor

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.

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow