2012-02-20 14 views
13

UPDATEコンパイルする方法:次のコードは、唯一のC#4.0(Visual Studioの2010)で理にかなって共分散/ contravariance:次のコードは、

私は、共分散/ contravariance物のいくつかの誤解が生じていますように思えます。誰も私に次のコードがコンパイルされない理由を教えてもらえますか?

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
     where TDerived: TBase 
    { 
     return values; 
    } 
} 

この1つはコンパイルしながら:(!!!)

public interface IBase 
{ 
} 
public interface IDerived: IBase 
{ 
} 
public class TestTwo 
{ 
    public IEnumerable<IBase> Method(IEnumerable<IDerived> values) 
    { 
     return values; 
    } 
} 

答えて

13

共分散は(型引数のための)タイプを参照するために適用されますので、あなたは、クラスの制約を追加する必要があります。

public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
    where TDerived : class, TBase 
{ 
    return values; 
} 

IEnumerable<int>IEnumerable<object>に変換しようとすると、無効になります。これは無効です。

+0

@Adam:私はあなたが間違っていると信じて、 'それもで' 3.5' – sll

+1

@AdamMihalcinをコンパイルしないように、デフォルトでは '' IEnumerableをのIEnumerableない ':いいえ、そのコード*はいないだろう* .NET 4より前にコンパイルしました。私はそれを検証するために自分で試しました。一般的な不変性がなければ、「IEnumerable 」から「IEnumerable 」への変換は単に無効です。 –

+0

TSuperで電話して、ちょうどそれを修正しました –

1

実際にTDerivedが必要な状況は考えられません。 TBaseを使用することで十分である:すべての後に

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method(IEnumerable<TBase> values) 
    { 
     return values; 
    } 
} 

、あなたはおよそTDerived離れ事実から、それはTBaseであるという情報を持っていない...

+2

残念ながら、それは私が複雑さのために作ったものではありません。私のコードで –

+1

@bonomo:それは面白いです、私は将来の参照のためのより詳細な例を見たいと思います。 :-) – linepogl

0

どちらも最初は私のためにコンパイル。どちらもSuper(T/I)からBase(T/I)への暗黙のキャストに失敗しました。しかし明示的なケースを追加すると、両方ともコンパイルされました。

public IEnumerable<TBase> Method<TSuper>(IEnumerable<TSuper> values) 
    where TSuper: TBase 
    { 
     return (IEnumerable<TBase>) values; 
    } 
関連する問題