私はこのようなセットアップを持っています:
abstract class Foo {}
class Bar : Foo {}
この形式の他の場所のメソッド:
void AddEntries(List<Foo>) {}
タイプBar
のオブジェクトのリストを使用してこのメソッドを呼び出そうとしています。
List<Bar> barList = new List<Bar>()
AddEntries(barList);
しかし、これは私にエラーを与えます:
list <Bar>からList <Foo>に変換できません
とにかくこの問題の周りにありますか?抽象クラスを使用してメソッド定義を保持する必要があります。
AddEntries
をジェネリックにし、これに変更できます
void AddEntries<T>(List<T> test) where T : Foo
{
//your logic
}
詳細については、 型パラメーターの制約 をご覧ください。
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:最初に指定したものよりも派生型を使用できます。
これは単純な理由で許可されていません。以下をコンパイルすると仮定します。
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
{
}