2011-10-20 15 views
7

Mam przykładowy program z podstawową klasą Fruit i pochodną klasy Apple.Jak dodać delegata jabłkowego do listy delegatów owoców?

class Testy 
{ 
    public delegate void FruitDelegate<T>(T o) where T : Fruit; 

    private List<FruitDelegate<Fruit>> fruits = new List<FruitDelegate<Fruit>>(); 

    public void Test() 
    { 
     FruitDelegate<Apple> f = new FruitDelegate<Apple>(EatFruit); 

     fruits.Add(f); // Error on this line 
    } 

    public void EatFruit(Fruit apple) { } 
} 

Chcę mieć listę delegatów owocowych i być w stanie dodać więcej delegatów owoców pochodzących z listy. Wierzę, że ma to coś wspólnego z kowariancją lub kontrawariancją, ale nie mogę tego zrozumieć.

komunikat Błąd jest (bez nazw):

The best overloaded method match for 'List<FruitDelegate<Fruit>>.Add(FruitDelegate<Fruit>)' has some invalid arguments` 

Odpowiedz

4

FruitDelegate <Fruit> jest delegatem, który akceptuje żadnych owoców. Na przykład poniższe nie jest ważny:

FruitDelegate<Fruit> f = new FruitDelegate<Fruit>(EatFruit); 
f(new Apple()); 
f(new Banana()); 

Można dokonać parametr typu T z FruitDelegate <T>contravariant:

public delegate void FruitDelegate<in T>(T o) where T : Fruit; 

który pozwala przypisać FruitDelegate <Fruit> instancja do FruitDelegate <Apple> zmienne:

FruitDelegate<Apple> f = new FruitDelegate<Fruit>(EatFruit); 
f(new Apple()); 

Jest to ważne, ponieważ pełnomocnik odnosi się do metody, która (między innymi owoce) przyjmuje jabłek.

Jednak nie można przypisać FruitDelegate < Jabłko > wystąpienie do FruitDelegate <Fruit> zmienna:

FruitDelegate<Fruit> f = new FruitDelegate<Apple>(EatApple); // invalid 
f(new Apple()); 
f(new Banana()); 

To nieważne, bo delegat powinien przyjmować żadnych owoców, ale odnoszą się do metoda, która nie akceptuje żadnych owoców innych niż jabłka.

Wniosek: nie można dodać FruitDelegate < Jabłko > wystąpienie do listy < FruitDelegate <Fruit> >, ponieważ FruitDelegate < Jabłko > nie jest FruitDelegate <Fruit>.