Let's say I have a generic class
public class G<T> {
}
and I want to declare final class as
public class F<T> where T : G<T> {
}
that seems to be possible, but what if I want to complicate the task and add a constraint to the class G like that
public class A {
}
public class DA : A {
}
public class DB : A {
}
public class G<T> where T : A {
}
and finally I want to do this
public class F<T> where T : G<T> {
}
that does not work, it says T has to be of type A which is understandable and it looks like I can rewrite it like this
public class F<T, U> where T : G<U> where U : A {
}
but in this case the usage has a redundant declaration
public class DF : F<G<DA>, DA> {
}
I have to repeat DA twice when using class F even though it is quite clear if I use G as a generic type the generic type of G is DA. Is there a way to avoid this redundancy?
But this doesn't seem to make much sense. You want
F
to be parametrized byT
which must beG<X>
whereX
isT
again, which isG<X>
, whereX
isT
again and so on... This is a recursive definition.I think what you actually want to define is something like (all examples are invalid C#)
or maybe
or maybe
Those kind of "generics of generics" are called higher-kinded types, but C#, unfortunately, does not support them. Haskell does for instance and some other functional languages do too.
There is a C# library that mimics HKTs and it uses the workaround you found: specifying the inner type twice.