This has been bothering me for a while. I'm having a little trouble understanding why explicit casts are needed in the following code:
public static class CastStrangeness
{
public class A
{
}
public class B
: A
{
}
public static void Foo<T>(T item)
where T : A
{
// Works.
A fromTypeParameter = item;
// Does not compile without an explicit cast.
T fromConcreteType = (T)fromTypeParameter;
// Does not compile without an explicit cast.
Foo<T>((T)fromTypeParameter);
}
public static void Bar(A item)
{
// Compiles.
Foo<A>(item);
}
}
It seems to me that T is guaranteed to be an A, so surely the compiler could infer that any instance of A is guaranteed to be assignable to T? Otherwise, I wouldn't be able to pass an A or a B into Foo(). So what am I missing?
PS. I've tried searching for endless permutations of keywords on this, but every result seems to wind up referring to covariance and contravariance WRT generic interfaces :)
Take the case of:
Foo(new B());
Your first assignment is ok:
A fromtypeParameter = item;
Since B : A.
But this assignment is not ok:
T fromConcreteType = fromTypeParameter;
Because you could very well have assigned fromTypeParameter as:
fromTypeParameter = new A();
Which you obviously cannot cast to T (which is B in this instance). T is more specific than A, it could be derived from A. So you can go one way but not the other, without an explicit cast (which may fail).
It seems to me that T is guaranteed to be an A, so surely the compiler could infer that any instance of A is guaranteed to be assignable to T?
Well, no.
string
is an object. But
string s = new object();
is illegal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With