2013-05-27 15 views
5

タイトルは私が何を話しているのか説明するのが難しいと思うので、説明するのが少し難しいので、コードで話しましょう。これをLINQPadにコピー&ペーストしてC#プログラムとして実行するか、ビジュアルスタジオで通常のC#プロジェクトとして必要な調整を行います(例:Dump()をConsole.Writeline()などに変更する) -ジェネリックオブジェクトは、必要なインターフェイスを実装していてもキャストが必要です

doStuffメソッドの行のコメントを外すと、コンパイルされません。

私の質問は、なぜgeneric2がすでにIab<TA,TB>を実装している場合にキャストが必要なのですか?これは共分散関係ですか?私はまだ.NET 3.5です。

void Main() 
{ 
    doStuff<a,b>(); 
} 

public void doStuff<TA, TB>() 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    Iab<TA, TB> x = null; 

    x = new generic1<TA, TB>(); 
    x.Go().Dump(); 

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?) 
    x = (Iab<TA, TB>) new generic2<TA>(); 
    x.Go().Dump(); 
} 

public interface Ia 
{} 

public interface Ib 
{} 

public class a : Ia 
{} 

public class b : Ib 
{} 

public interface Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    string Go(); 
} 

public class generic1<TA, TB> : Iab<TA,TB> 
where TA : class, Ia, new() 
where TB : class, Ib, new() 
{ 
    public string Go() 
    { 
     return "generic Base called"; 
    } 
} 

public class generic2<TA> : Iab<TA,b> 
where TA : class, Ia, new() 
{ 
public string Go() 
    { 
     return "generic Sub called"; 
    } 
} 

答えて

4

私は1つまたは複数のタイプの(この場合は、TS)はコンパイル時に知られていないときは、必ずそのエラーを取得するためであると考えています。

コンパイラは互換性のある型でdoStuff()が呼び出されることを保証できないため、強制的にキャストします。コンパイラはこれを行うことができない理由

を確認するには、次のように doStuff()を呼び出してみてください。

public class X: b {} 

... 

doStuff<a, X>(); // Compiles ok but: 

未処理の例外:System.InvalidCastExceptionの:「をgeneric2 1[Demo.Program+X]' to type 'Iab 2 [デモを型のオブジェクトをキャストすることができません。 Program + X、Demo.Program + Y] 'を選択します。

したがって、クラッシュするタイプで呼び出すことは可能です。コンパイラはあなたがそれを静かにさせることはありません。

+0

もちろん、はい、もちろんです。それを逃した:)感謝! –