Generic class type constraint with a generic class having another constraint

268 views Asked by At

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?

1

There are 1 answers

5
Good Night Nerd Pride On

And finally I want to do this

public class F<T> where T : G<T> {
}

But this doesn't seem to make much sense. You want F to be parametrized by T which must be G<X> where X is T again, which is G<X>, where X is T 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#)

public class F<T1<T2>> where T1 : G<T2> where T2 : A {
}

or maybe

public class F<T1> where T1 : G<T2> where T2 : A {
}

or maybe

public class F<G<T>> where T : A {
}

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.