C# generic constraint: type parameter on the class inherits type parameter on the method?

Executive summary: Chris Hannon's answer is basically correct However, there are sneaky tricks involving interfaces and extension methods that might get you what you want Excessive details: We do occasionally get asked for this sort of constraint, and there are other languages that have constraints like this. Java and I believe Scala both have ways of saying "this has to be a supertype of that". As others have pointed out, this sort of constraint cannot be represented in either the C# type system or the underlying CLR type system The reason why you might want this sort of variance would be for a situation like this: class ImmutableStack { public static ImmutableStack Empty { get { return empty; } } private static ImmutableStack empty = new ImmutableStack(); private T head; private ImmutableStack tail; public ImmutableStack Pop() { if (this == empty) throw new Exception(); return this.

Tail; } public ImmutableStack Push(N value) where T : N // not legal { var result = new ImmutableStack(); result. Head = value; result. Tail = this; // also not legal return result; } } And now you can do something like: Tiger tony = new Tiger(); Elephant dumbo = new Elephant(); ImmutableStack tigers = ImmutableStack.

Empty; tigers = tigers. Push(tony); ImmutableStack mammals = tigers. Push(dumbo) And hey, now you can push an elephant onto a stack of tigers and it magically becomes a stack of mammals!

This is not possible in C# as I've shown here for two reasons: first, because there is no such generic constraint, and second, because immutable class types are not covariant. (The assignment to the tail requires covariance. ) However it is possible to do this in C# if you are sneaky You can get around the covariance problem by representing everything as a covariant interface rather than a class.

You can get around the "no such constraint" problem by moving the method in question out of the class proper and making it into an extension method! I give an example of how to do so here: http://blogs.msdn.com/b/ericlippert/archive/2007/12/06/immutability-in-c-part-three-a-covariant-immutable-stack.aspx.

Executive summary: Chris Hannon's answer is basically correct. However, there are sneaky tricks involving interfaces and extension methods that might get you what you want. Excessive details: We do occasionally get asked for this sort of constraint, and there are other languages that have constraints like this.

Java and I believe Scala both have ways of saying "this has to be a supertype of that". As others have pointed out, this sort of constraint cannot be represented in either the C# type system or the underlying CLR type system. The reason why you might want this sort of variance would be for a situation like this: class ImmutableStack { public static ImmutableStack Empty { get { return empty; } } private static ImmutableStack empty = new ImmutableStack(); private T head; private ImmutableStack tail; public ImmutableStack Pop() { if (this == empty) throw new Exception(); return this.

Tail; } public ImmutableStack Push(N value) where T : N // not legal { var result = new ImmutableStack(); result. Head = value; result. Tail = this; // also not legal return result; } } And now you can do something like: Tiger tony = new Tiger(); Elephant dumbo = new Elephant(); ImmutableStack tigers = ImmutableStack.

Empty; tigers = tigers. Push(tony); ImmutableStack mammals = tigers. Push(dumbo); And hey, now you can push an elephant onto a stack of tigers and it magically becomes a stack of mammals!

This is not possible in C# as I've shown here for two reasons: first, because there is no such generic constraint, and second, because immutable class types are not covariant. (The assignment to the tail requires covariance. ) However it is possible to do this in C# if you are sneaky.

You can get around the covariance problem by representing everything as a covariant interface rather than a class. You can get around the "no such constraint" problem by moving the method in question out of the class proper and making it into an extension method! I give an example of how to do so here: http://blogs.msdn.com/b/ericlippert/archive/2007/12/06/immutability-in-c-part-three-a-covariant-immutable-stack.aspx.

1 for the covariant interface/extension method approach, that's an interesting trick to handle this. – Chris Hannon Jul 14 at 21:16.

You can't do what you're asking to do in C#. Constraints essentially specify a common assignable point that something must have, and constraining TMethod : TClass will mean that you know that TMethod can at least be treated as TClass. The problem with constraining TMethod to be "somewhere within the inheritance structure of another type" is that you now have no good way to determine a base type for what you're being given, as far as constraints go.

Are you using a specific interface implemented by a base class three levels deep in a completely different type? Are you passing in a base class? Are you passing an unrelated descendant class whose base just happens to fall into the object's inheritance structure?

Object is the closest you'll get that matches all possible combinations, and at that point you may as well just forget about using generics and use Object directly because all of the type-safety benefits provided by generics have been thrown out the window. Reversing that would also defeat the purpose of polymorphism. If a method signature requires class A and my type descends from class A, why should I not be allowed to pass it in as A?

If the reverse was true and a method signature potentially expects any base class of B and specifies B instead, you cannot reasonably expect that any functionality of B will be available if you were able to pass in A.

1 for the reasoning behind why this constraint would not make sense. The available behavior would need to be restricted to that provided by Object, so you might as well just pass Object. – Dan Bryant Jul 14 at 17:19.

You can't do that because TClass is not defined in the method type signature. TClass is defined at the class level, therefor you can't constraint it at a method level. Try... class GenericClass { public void DoSomething(TMethod input) where TMethod : TClass { // ... } } This is saying, allow this method to be called where TMethod is assignable from TClass.

Please see my update for a clarification on what I'm trying to achieve. – Tomas Lycken Jul 14 at 16:09 TMethod : TClass actually means that TClass must be assignable from TMethod (so if TClass is type BaseClass, any class deriving from BaseClass may be used for TMethod; a variable of type BaseClass could be assigned any of those derivative types. ) – Dan Bryant Jul 14 at 17:32.

The closest you're going to get, I think, is to pass Object and perform a runtime check for the inheritance relationship. Class GenericClass { public void DoSomething(Object input) { if (input == null) throw new ArgumentNullException("input"); if (!input.GetType(). IsAssignableFrom(typeof(TClass))) throw new ArgumentException("Input type must be assignable from " + typeof(TClass).ToString(), "input"); // ... } } Note that this will permit inputs of type Object and also (in rare circumstances with transparent remoting proxies) of an interface type that TClass implements.

These could be explicitly excluded as well.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions