【问题标题】:How to add an apple delegate to a list of fruit delegates?如何将苹果代表添加到水果代表列表中?
【发布时间】:2011-10-20 00:34:43
【问题描述】:

我有一个示例程序,它有一个基本的 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`

【问题讨论】:

    标签: c# generics delegates covariance contravariance


    【解决方案1】:

    FruitDelegate 是一个接受任何水果的委托。例如,以下是有效的:

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

    可以将FruitDelegate的类型参数T设为contravariant:

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

    允许您将 FruitDelegate 实例分配给 FruitDelegate 变量:

    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 实例添加到 List>,因为 FruitDelegate 不是 FruitDelegate

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-01
      • 1970-01-01
      • 2019-12-28
      • 2021-04-09
      • 2019-09-21
      • 2018-11-28
      • 2018-01-07
      • 2020-01-10
      相关资源
      最近更新 更多