web-dev-qa-db-ja.com

List <Bar>からList <Foo>に変換できません

私はこのようなセットアップを持っています:

abstract class Foo {}
class Bar : Foo {}

この形式の他の場所のメソッド:

void AddEntries(List<Foo>) {}

タイプBarのオブジェクトのリストを使用してこのメ​​ソッドを呼び出そうとしています。

List<Bar> barList = new List<Bar>()
AddEntries(barList);

しかし、これは私にエラーを与えます:

list <Bar>からList <Foo>に変換できません

とにかくこの問題の周りにありますか?抽象クラスを使用してメソッド定義を保持する必要があります。

42
user3041702

AddEntriesをジェネリックにし、これに変更できます

void AddEntries<T>(List<T> test) where T : Foo
{
    //your logic 
}

詳細については、 型パラメーターの制約 をご覧ください。

65
Mighty Badaboom

docs.Microsoft.comからのGenericsの共分散と共分散 を読んでください。特にセクション「共変型パラメーターを持つジェネリックインターフェイス」で説明します。作業しているシナリオから外れます。

つまり、AddEntriesメソッドの署名を(に)変更できる場合:

static void AddEntries(IEnumerable<Foo> entries)

IEnumerable<Foo>の代わりにList<Foo>を使用していることに注意してください)、目的のことを実行できます。

ここでの具体的な違いは、IEnumerable<T>List<T>の宣言が異なることです。

public interface IEnumerable<out T> : IEnumerable
public class List<T> : IList<T>, ... ...

mattersの違いは、IEnumerable<T>の宣言のoutであり、covariant意味します(docs.Microsoft.comからの定義を使用):

Covariance:最初に指定したものよりも派生型を使用できます。

60
Rob

これは単純な理由で許可されていません。以下をコンパイルすると仮定します。

AddEntries(new List<Bar>());

void AddEntries(List<Foo> list)
{
   // list is a `List<Bar>` at run-time
   list.Add(new SomethingElseDerivingFromFoo()); // what ?!
}

コードがコンパイルされる場合、SomethingElseDerivingFromFooを実際にList<Bar>(実行時タイプ)。

問題を解決するには、ジェネリックを使用できます。

void AddEntries<T>(List<T> list) where T:Foo
{

}
43
Zein Makki