4

同じインターフェイスから継承する 3 つのクラスがあります。

Apple:Resource
Banana:Resource
Orange:Resource

私は別のクラスで、それぞれ op 型のリストを持っています:

private List<Apple> apples = new List<Banana>();
private List<Banana> bananas = new List<Empleado>();
private List<Orange> oranges = new List<Orange>();

ここで、これらのリストのいずれかを返すことができるメソッドが必要です。次のように言いましょう。

public List<Resource> getListOf(string resource)
{
    switch (resource)
    {
        case "apple": 
            return apples;
            break;
        case "bananas":
        return bananas;
            break;
        case "oranges":
        return oranges;
            break;
        default:
            Console.WriteLine("wrong fruit");
            break;
    }
}

これにより、次のエラーが表示されます。

System.Collections.Generic.List<Fruits.Apple>タイプ ' ' を ' ' にSystem.Collections.Generic.List<Fruits.Resource>暗黙的に変換することはできません

私ができるのと同じように機能すると思いました:

foreach (Resource r in Fruitlist) {
    r.Meth();
}
4

1 に答える 1

7

コードが存在しないことでコードが壊れる機能は、ジェネリック型共分散と呼ばれます。C# はgenericsのバリアンスをサポートしていますが、インターフェイス (具体的なクラスではない) でのみサポートしています。

foreachスニペットは として扱わFruitlistれるため機能し、これは(共変の) 型パラメーターIEnumerable<Fruit>を持つ汎用インターフェイスであるため、コンパイラーはそれを として表示できます。outIEnumerable<Resource>

getListOfがを返すことが許容される場合IEnumerable<Resource>は、関数のシグネチャを変更するとコードがコンパイルされます。そうしないと、次のコードを記述できるため、コンパイラは型の安全性を保証できません。

List<Resource> apples = this.getListOf("apple");
apples.Add(new Orange()); // adding a Resource to a List<Resource>, right?

別のオプションは、非ジェネリック型を返すことです。その場合、型の安全性が再び失われ、コンパイラは実行時チェックを導入して、リンゴとオレンジを混ぜないようにします (ただし、少なくともコードは動作します)行儀が良い)。

于 2013-06-14T22:37:30.000 に答える