Why can I only upcast a generic and not downcast it?
How is it not clear to the compiler that if my constraint says where T : BaseClass
and U is derived from BaseClass that (U)objectOfTypeT
is valid?
Asked
Active
Viewed 999 times
4

the_drow
- 18,571
- 25
- 126
- 193
-
2If it helps, note you can add a cast to object in the middle if you want to overrule the compiler. – Marc Gravell Oct 24 '10 at 08:25
-
1@Marc Gravell: That helps a lot. thanks. – the_drow Oct 24 '10 at 09:13
2 Answers
5
Because it might not be valid. Consider this:
class Base { }
class A : Base { }
class B : Base { }
A temp1 = new A();
B temp2 = (B)temp1; // not valid
Just because they share the same base class does not mean that you can typecast one to the other.
Note that you can get around this by using the as
operator:
var result = objectOfTypeT as U; // this does not give any compilation error
// but will result in a null reference if
// objectOfTypeT cannot be converted to U

Fredrik Mörk
- 155,851
- 29
- 291
- 343
-
-
@the_drow: I can only speculate, but it feels like that would counteract the purpose of generics; one key element of generics is to achieve type safety. Allowing this potentially failing cast would defeat that purpose. – Fredrik Mörk Oct 24 '10 at 08:20
-
After searching google a bit. What about covariance and contravariance? Is this what I am looking for? – the_drow Oct 24 '10 at 08:26
-
-
I have a generic unit test for every class that inherits from Base. The only difference is the outcoming result. I can already tell what T will be and only need to downcast it to check the outcoming result. – the_drow Oct 24 '10 at 09:12
-
@the_drow: it seems you can get around this by using the `as` operator; check updated answer. – Fredrik Mörk Oct 24 '10 at 10:41
2
Unless I read the question wrong, you could have:
class A:BaseClass{}
class B:BaseClass{}
With T=A and U=B, both constraints are happy, but the cast from T to U is clearly invalid.
If U is just another class, then the same still applies; the T is not known to be in the same chain as U unless you state it in the constraints (generic constraints can involve other generic type arguments, if it helps).

Marc Gravell
- 1,026,079
- 266
- 2,566
- 2,900
-
Well no, I am not casting from T to U but from T to A where T is A and the constraint is where T : BaseClass. – the_drow Oct 24 '10 at 08:16
-