Consider this made-up example...
public abstract class CollectionItem<TSelf> {
protected CollectionItem(ICollection<TSelf> siblings)
=> Siblings = siblings;
public ICollection<TSelf> Siblings { get; }
}
public class Foo : CollectionItem<Foo>{
public Foo()
: base(new FooCollection){}
}
public class FooCollection : ObservableCollection<Foo>{
}
With the above, Foo now has a Siblings property. However, there are three problems with this.
- I have to repeat the redundant
Fooin the generic Siblingsitself isn't typed to the actual collection type, but rather the interface.- I have to actually pass in an instance of the
Siblingscollection
Solving for #2 and #3, I made this change...
public class CollectionItem<TSelf, TSiblings>
where TSiblings : ICollection<TSelf>, new() {
protected CollectionItem()
=> Siblings = new TSiblings();
public TSiblings Siblings { get; }
}
but I still have to pass in the seemingly redundant Foo as the first type parameter, like this...
public class Foo : CollectionItem<Foo, FooCollection>{
}
In Swift, you have an implicit Self datatype which always represents the type of the current instance, meaning if Self is used in a base class, it's actually a stand-in for the data type of the subclass. Think of it as an implicit generic if you will.
Having that in C# would allow me to do something like this...
public class CollectionItem<TSiblings>
where TSiblings : ICollection<Self>, new() { // Note it uses 'Self' here
protected CollectionItem()
=> Siblings = new TSiblings();
public TSiblings Siblings { get; }
}
public class Foo : CollectionItem<FooCollection>{
}
public class Laa : CollectionItem<LaaCollection>{
}
In the above, for instances of Foo, Self refers to Foo. For instances of Laa, Self refers to Laa. No need to pass the redundant type parameters.
So does C# have anything similar?