2011-10-20 68 views
7

我有一個基地Fruit類和派生Apple類的示例程序。如何將一個蘋果委託添加到水果委託人列表中?

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) { } 
} 

我想要一個水果代表的列表,並能夠將更多派生水果的代表添加到列表中。我相信這與協變或逆變有關,但我似乎無法弄清楚。

該錯誤消息是(沒有命名空間):

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

回答

4

FruitDelegate <水果>是接受任何水果的委託。例如,以下是有效的:

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

你可以讓類型參數FruitDelegate的牛逼<牛逼>contravariant

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

,它允許你指定一個FruitDelegate <水果>實例到FruitDelegate <Apple>變量:

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

這是有效的,因爲該委託指(在其他水果)接受蘋果的方法。

但是,你無法分配FruitDelegate <蘋果>實例爲FruitDelegate <水果>變量:

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

這是無效的,因爲代表應該接受任何水果,但要提到除蘋果以外不接受任何水果的方法。

結論:你不能添加FruitDelegate <蘋果>實例爲列表< FruitDelegate <水果> >,因爲FruitDelegate <蘋果>不是FruitDelegate <水果>