I have a sample program with a base Fruit
class and a derived Apple
class.
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) { }
}
I want to have a list of fruit delegates and be able to add delegates of more derived fruit to the list. I believe this has something to do with covariance or contravariance but I cannot seem to figure it out.
The error message is (without namespaces):
The best overloaded method match for 'List<FruitDelegate<Fruit>>.Add(FruitDelegate<Fruit>)' has some invalid arguments`
A FruitDelegate<Fruit> is a delegate that accepts any fruit. For example, the following is valid:
FruitDelegate<Fruit> f = new FruitDelegate<Fruit>(EatFruit);
f(new Apple());
f(new Banana());
You can make the type parameter T of FruitDelegate<T> contravariant:
public delegate void FruitDelegate<in T>(T o) where T : Fruit;
which allows you to assign a FruitDelegate<Fruit> instance to a FruitDelegate<Apple> variable:
FruitDelegate<Apple> f = new FruitDelegate<Fruit>(EatFruit);
f(new Apple());
This is valid, because the delegate refers to a method that (among other fruits) accepts apples.
However, you cannot assign a FruitDelegate<Apple> instance to a FruitDelegate<Fruit> variable:
FruitDelegate<Fruit> f = new FruitDelegate<Apple>(EatApple); // invalid
f(new Apple());
f(new Banana());
This is invalid, because the delegate should accept any fruit, but would refer to a method that accepts no fruit other than apples.
Conclusion: you cannot add a FruitDelegate<Apple> instance to a List<FruitDelegate<Fruit>>, because a FruitDelegate<Apple> is not a FruitDelegate<Fruit>.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With