I stumbled across this odd case yesterday, where t as D
returns a non-null value, but (D)t
causes a compiler error.
Since I was in a hurry I just used t as D
and carried on, but I am curious about why the cast is invalid, as t
really is a D
. Can anyone shed some light on why the compiler doesn't like the cast?
class Program
{
public class B<T> where T : B<T> { }
public class D : B<D> { public void M() { Console.Out.WriteLine("D.M called."); } }
static void Main() { M(new D()); }
public static void M<T>(T t) where T : B<T>
{
// Works as expected: prints "D.M called."
var d = t as D;
if (d != null)
d.M();
// Compiler error: "Cannot cast expression of type 'T' to type 'D'."
// even though t really is a D!
if (t is D)
((D)t).M();
}
}
EDIT: Playing around, I think this is a clearer example. In both cases t
is constrained to be a B
and is maybe a D
. But the case with the generic won't compile. Does the C# just ignore the generic constraint when determining if the cast is legal? Even if it does ignore it, t
could still be a D
; so why is this a compile time error instead of a runtime exception?
class Program2
{
public class B { }
public class D : B { public void M() { } }
static void Main()
{
M(new D());
}
public static void M(B t)
{
// Works fine!
if (t is D)
((D)t).M();
}
public static void M<T>(T t) where T : B
{
// Compile error!
if (t is D)
((D)t).M();
}
}