私は昨日この奇妙なケースに出くわしました。そこでt as D
はnull以外の値が返されます(D)t
が、コンパイラエラーが発生します。
急いでいたので使いt as D
続けたのですが、キャストが無効な理由が気になりt
ますD
。コンパイラがキャストを好まない理由を誰かが明らかにすることはできますか?
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();
}
}
編集:遊んで、これはより明確な例だと思います。どちらの場合もt
、に制約され、B
おそらくはD
です。しかし、ジェネリックの場合はコンパイルされません。キャストが合法かどうかを判断するときに、C#は一般的な制約を無視しますか?それがそれを無視したとしても、t
それでもD
;である可能性があります。では、なぜこれが実行時例外ではなくコンパイル時エラーなのですか?
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();
}
}