Разве это не странно, потому что 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());
Хорошо.Да является делегатом метода, который принимает любое млекопитающее.Метод, который берет любое животное ясно, также берет любое млекопитающее.Вы можете назначить 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.Для получения дополнительной информации по этой теме см. Мою статью:
http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx