这不是很奇怪吗,因为 B 扩展了 A?
你的想法是正确的,但方向错误。让我们考虑一个更容易推理的例子:
class Animal {}
class Reptile : Animal {}
class Snake : Reptile {}
class Mammal : Animal {}
class Tiger : Mammal {}
class Giraffe : Mammal {}
delegate void D(Mammal m);
static void DoAnimal(Animal a) {}
static void DoMammal(Mammal m) {}
static void DoTiger(Tiger t) {}
D dm = DoMammal;
dm(new Tiger());
这显然是合法的。 dm 需要是一种采用哺乳动物的方法,而且确实如此。
D dt = DoTiger;
dt(new Giraffe());
这显然是违法的。您不能将捕获老虎的方法分配给捕获哺乳动物的委托,因为捕获哺乳动物的委托可以捕获任何哺乳动物,而不仅仅是老虎。如果这是合法的,那么就有可能将长颈鹿传递给老虎的方法。
那这个呢?
D da = DoAnimal;
da(new Giraffe());
没关系。 da 是接受任何哺乳动物的方法的代表。显然,适用于任何动物的方法也适用于任何哺乳动物。您可以将 DoAnimal(Animal) 分配给委托 D(Mammal),因为 Mammal 扩展了 Animal。现在您知道如何向后延伸的方向了吗?
返回类型另一方面,按照您认为的方式工作:
delegate Mammal F();
static Animal GetAnimal() {...}
static Mammal GetMammal() {...}
static Tiger GetTiger() {...}
F fm = GetMammal;
Mammal m = fm();
那里没问题。
F ft = GetTiger;
Mammal t = ft();
没问题; GetTiger 返回一只老虎,因此您可以将其分配给要求其目标返回哺乳动物的委托。
F fa = GetAnimal;
Mammal a = fa();
那可不好。 GetAnimal 可能会返回一条 Snake,现在您有一个类型为 Mammal 的变量,其中包含一条 Snake。这一定是非法的。
此功能称为“成员组转换的协变和逆变”,在 C# 2.0 中引入。有关此主题的更多信息,请参阅我的文章:
https://ericlippert.com/2007/10/19/covariance-and-contravariance-in-c-part-3-method-group-conversion-variance/ https://ericlippert.com/2007/10/19/covariance-and-contravariance-in-c-part-3-method-group-conversion-variance/