5

たとえば、次のクラスがあるとします。

public class MyFoo : IMyBar
{
    ...
}

次に、次のコードを使用したいと思います。

List<MyFoo> classList = new List<MyFoo>();
classList.Add(new MyFoo(1));
classList.Add(new MyFoo(2));
classList.Add(new MyFoo(3));

List<IMyBar> interfaceList = new List<IMyBar>(classList);

しかし、これはエラーを生成します:

`Argument '1': cannot convert from 'IEnumerable<MyFoo>' to 'IEnumerable<IMyBar>' 

どうしてこれなの?MyFoo は IMyBar を実装しているため、MyFoo の IEnumerable を IMyBar の IEnumerable として扱うことができると考えられます。ありふれた現実世界の例として、車のリストを作成した後、それは車のリストではないと言われたことがあります。

それはほんの些細な迷惑ですが、誰かがこれに光を当てることができれば、私は大いに義務付けられます.

4

4 に答える 4

14

これは C# 4.0 で機能します。あなたが話していることは、一般的な共分散と呼ばれます。

Castそれまでの間、拡張メソッドを使用できます:

List<IMyBar> interfaceList = new List<IMyBar>(classList.Cast<IMyBar>());
于 2010-03-22T21:29:08.640 に答える
3

これは.NET4.0でサポートされていますが、それ以前ではサポートされていません。

http://msdn.microsoft.com/en-us/library/dd799517%28VS.100%29.aspx

于 2010-03-22T21:30:14.877 に答える
3

明確にするために、現在機能しない理由は、IEnumerable<MyClass>から継承されていないためIEnumerable<MyBar>です。繰り返しますが、派生型の列挙型は、基本型の列挙型から継承されません。IEnumerable<T>むしろ、どちらの型もジェネリック型を特殊化します。.Net 3.5 以前では、特殊化 (継承ではない) 以外の関係はなく、それ以外は型システムで 2 つの完全に異なる型です。

.Net 4.0 は、これらの型の関係をまったく変更しません。それらは、専門化によってのみ関連する 2 つの完全に異なるタイプのままです。これにより、特殊化の関係を認識するメソッドを記述できるようになり、場合によっては、別のメソッドを記述したときに一方を置き換えることができるようになります。

于 2010-03-22T21:37:08.920 に答える
1

リスト間ではなく(質問の見出しに書いたように)IEnumerable間でキャストしたい場合(質問に書いたように)、c#4.0共分散機能を待つことができます。その日までは、拡張メソッドを使用できます。ただし、他の回答に記載されているキャスト拡張メソッドは使用しませんが、IEnumerable での共分散キャストにのみ使用できる独自のメソッドを作成します。C# 4.0 に切り替えると、キャストが冗長になるコード内のすべての場所を簡単に見つけることができます。

public static class cEnumerableExtensions
{
    public static IEnumerable<TResult> CovarianceConversion<TResult, TSource>(this IEnumerable<TSource> source)
        where TSource : TResult
    {
        foreach (var item in source)
        {
            yield return item;
        }
    }
}

最終ノード。netframework 4.0 のプリコンパイラ定数はないようです。それ以外の場合は追加します

    #if DOTNET4
    [Obsolete("You can directly cast in C# 4.0.")]
    #endif
于 2010-03-22T22:36:57.443 に答える