我有一个基本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`
答案 0 :(得分:4)
FruitDelegate&lt; Fruit&gt; 是一个接受任何水果的代表。例如,以下内容有效:
FruitDelegate<Fruit> f = new FruitDelegate<Fruit>(EatFruit);
f(new Apple());
f(new Banana());
您可以创建 FruitDelegate&lt; T&gt; contravariant的类型参数 T :
public delegate void FruitDelegate<in T>(T o) where T : Fruit;
允许您将 FruitDelegate&lt; Fruit&gt; 实例分配给 FruitDelegate&lt; Apple&gt; 变量:
FruitDelegate<Apple> f = new FruitDelegate<Fruit>(EatFruit);
f(new Apple());
这是有效的,因为委托引用了一种方法(其他水果)接受苹果。
但是,您无法将 FruitDelegate&lt; Apple&gt; 实例分配给 FruitDelegate&lt; Fruit&gt; 变量:
FruitDelegate<Fruit> f = new FruitDelegate<Apple>(EatApple); // invalid
f(new Apple());
f(new Banana());
这是无效的,因为委托应该接受任何水果,但是会引用除了苹果之外不接受任何水果的方法。
结论:您无法将 FruitDelegate&lt; Apple&gt; 实例添加到 List&lt; FruitDelegate&lt; Fruit&gt;&gt; ,因为 FruitDelegate&lt; Apple&gt; 不是 FruitDelegate&lt; Fruit&gt; 。