2009-05-04 9 views
1

とサブクラスのコレクションを追加します> .AddRange(一覧<B>)コンパイラは拒否する:はAddRange

Argument '1': cannot convert from 'System.Collections.Generic.List<A>' 
to 'System.Collections.Generic.IEnumerable<B> 

私は完全に理解しているIEnumerableを<理由B >はIEnumerable < A>を継承しません。その汎用型には継承があります。一覧< > .Add(アイテム)がB項目で動作しますので、

私のソリューションは、リスト<B>を列挙し、個別の項目を追加することです:

foreach(B item in listOfBItems) 
{ 
    listOfAItems.Add(item); 
} 

はしかし、それはむしろ非表情豊かだから私が欲しいのはちょうどAddRangeです。

私は

List<B>.ConvertAll<A>(delegate(B item) {return (A)item;}); 

を使用することができますが、それは不必要に複雑だと私は変換していないよので誤った名称は、私がキャスティングです。

質問:私は私がリストにワンライナー同類としてののコレクションにBさんのコレクションをコピーできるようになり、私はそれに追加するどのような方法で自分のリストのようなコレクションを記述した場合<A> .AddRange(リスト<B >)およびは、最大の型安全性を保持します。 (そして最大限私は引数がコレクション型継承チェックの両方であることを意味します)。

答えて

1

これは残念ながら動作しません.netのジェネリックは共分散をサポートしていないためです。

ただし、この問題を解決するための小さなヘルパーメソッドまたはクラスを作成することはできます。

あなたがあなた自身のリストクラスを実装する場合は、追加の一般的なパラメータを使用して共分散を追加することができますが:

class MyList<T> { 
    void AddRange<U>(IEnumerable<U> items) where U: T { 
     foreach (U item in items) { 
      Add(item); 
     } 
    } 
} 
0

私が思い付くことができる唯一のことはやって意味、それを呼び出すと、この

public class MyList<T> : List<T> 
{ 
    public void AddRange<Tother>(IEnumerable<Tother> col) 
     where Tother: T 
    {  
     foreach (Tother item in col) 
     { 
      this.Add(item); 
     } 
    } 
} 

ですMyList <A> .AddRange <B>(MyList <B>)。これは、引数が列挙できない場合、または型継承が機能しないため、質問の最大型安全性要件を満たす場合には失敗します。

+0

"引数が列挙できない場合や、型の継承がうまくいかない場合は失敗します。"という推論から利益を得ることができます。それは少なくとも私にとっては期待される行動です。あなたは何を期待していますか、またはこれはどのように問題になりますか? – Lucero

+0

それはまさに私が疑うところです。私はこれが最大の型安全性に関する私の質問の要求を満たすと言っていました。 –

+0

コンパイラは型が互換性があることをコンパイラが知っているので(「編集」で追加したかどうかわからない)、「item」から「T」へのキャストは不要です。 – Lucero

1

は、あなただけ行うことはできません。

listOfAItems.AddRange(listOfBItems.Cast<A>()); 
+0

私はリスト .Cast ()メソッドを持っていません。 –

+0

System.Linqを参照していますか? .NET 2.0に対して実行している場合は、キャストがLinq拡張メソッドの1つであることを謝ります。 – BFree

+0

Trueであり、.NETバージョン3.5以降でのみ使用可能です。しかし、拡張メソッドはコード内で「クリーン」ですが、必ずしも効率的というわけではありません。この場合、ジェネリックパラメータを使用するアプローチは、頻繁に呼び出されるとはるかに高速です。 – Lucero

1

を私が...

listOfAItems.AddRange(listOfBItems.Cast<A>()); 
+1

ここにある質問/回答の詳細については、こちらのhttp://stackoverflow.com/aboutを参照してください。あなたの投稿は質問に答えていません。 ** BFreeの回答**へのコメントです。評判を上げると追加することができます:http://stackoverflow.com/faq#reputation –

1

あなたはどこジェネリック型な状況に自分自身を見つける場合には、この使用してLINQを達成することができました

public static void AddRange<TList,TOther>(this List<TList> list, IEnumerable<TOther> collection) where TOther: TList { 
    foreach(TOther e in collection) { 
     list.Add(e); 
    } 
} 

代わりList<T>から派生したか、この私を有するので:バリアント、以下の拡張メソッドは、あなたの人生を容易にすることができませんいくつかのユーティリティクラスでは、拡張メソッドとして使用すると、使用が簡単になります。

List<Animal> animals; 
List<Dog> dogs; 
animals.AddRange(dogs); 
関連する問題