Console.WriteLine("Xob: " + Xob.Val);
// В этом случае возвращаемым типом метода IncrB служит объект класса Y, // а возвращаемым типом делегата Changelt — объект класса X. Но благодаря // ковариантности следующая строка кода оказывается вполне допустимой, change = IncrB;
Yob = (Y) change(Yob);
Console.WriteLine("Yob: " + Yob.Val);
}
}
Вот к какому результату приводит выполнение этого кода.
Xob: 1 Yob: 1
В данном примере классYявляется производным от классаX.А делегатChangeltобъявляется следующим образом.
delegate X Changelt(Y obj);
Делегат возвращает объект классаXи принимает в качестве параметра объект классаY.А методыIncrA() иIncrB() объявляются следующим образом.
static X IncrA(X obj) static Y IncrB(Y obj)
МетодIncrA() принимает объект классаXв качестве параметра и возвращает объект того же класса. А методIncrB() принимает в качестве параметра объект классаYи возвращает объект того же класса. Но благодаря ковариантности и контравари-антности любой из этих методов может быть передан делегатуChangelt,что и демонстрирует рассматриваемый здесь пример.
Таким образом, в строке
Changelt change = IncrA;
методIncrA() может быть передан делегату благодаря контравариантности, так как объект классаXслужит в качестве параметра методаIncrA (), а объект классаY —в качестве параметра делегатаChangelt.Но метод и делегат оказываются совместимыми в силу контравариантности, поскольку типом параметра метода, передаваемого делегату, служит класс, являющийся базовым для класса, указываемого в качестве типа параметра делегата.
Приведенная ниже строка кода также является вполне допустимой, но на этот раз благодаря ковариантности.
change = IncrB;
В данном случае возвращаемым типом для методаIncrB() служит классY,а для делегата — класс X. Но поскольку возвращаемый тип метода является производным классом от возвращаемого типа делегата, то оба оказываются совместимыми в силу ковариантности.
Класс System. Delegate
Все делегаты и классы оказываются производными неявным образом от классаSystem. Delegate.Как правило, членами этого класса не пользуются непосредственно, и этоНеделается явным образом в данной книге. Но члены классаSystem. Delegateмогут оказаться полезными в ряде особых случаев.
Назначение делегатов