// Создать объект делегата BinaryOp, который
// "указывает" на SimpleMath.Add().
BinaryOp b = new BinaryOp(SimpleMath.Add);
// Вызвать метод Add() косвенно с использованием объекта делегата.
Console.WriteLine("10 + 10 is {0}", b(10, 10));
Console.ReadLine();
// Дополнительные определения типов должны находиться
// в конце операторов верхнего уровня.
// Этот делегат может указывать на любой метод,
// принимающий два целых числа и возвращающий целое число.
public delegate int BinaryOp(int x, int y);
На заметку!
Вспомните из главы 3, что дополнительные определения типов (делегатBinaryOp в этом примере) должны располагаться после всех операторов верхнего уровня.И снова обратите внимание на формат объявления типа делегата BinaryOp
BinaryOp могут указывать на любой метод, принимающий два целочисленных значения и возвращающий целочисленное значение (действительное имя метода, на который он указывает, к делу не относится). Здесь мы создали класс по имени SimpleMath, определяющий два статических метода, которые соответствуют шаблону, определяемому делегатом BinaryOp.Когда вы хотите присвоить целевой метод заданному объекту делегата, просто передайте имя нужного метода конструктору делегата:
// Создать объект делегата BinaryOp, который
// "указывает" на SimpleMath.Add().
BinaryOp b = new BinaryOp(SimpleMath.Add);
На данной стадии метод, на который указывает делегат, можно вызывать с использованием синтаксиса, выглядящего подобным прямому вызову функции:
// На самом деле здесь вызывается метод Invoke()!
Console.WriteLine("10 + 10 is {0}", b(10, 10));
"За кулисами" исполняющая среда вызывает сгенерированный компилятором метод Invoke()
MulticastDelegate классе. В этом можно удостовериться, открыв сборку в утилите ildasm.exe и просмотрев код CIL внутри метода Main():.method private hidebysig static void Main(string[] args) cil managed
{
...
callvirt instance int32 BinaryOp::Invoke(int32, int32)
}
Язык C# вовсе не требует явного вызова метода Invoke()
BinaryOp может указывать на методы, которые принимают два аргумента, следующий оператор тоже допустим:Console.WriteLine("10 + 10 is {0}", b.Invoke(10, 10));
Вспомните, что делегаты .NET Core
SimpleMath теперь определен дополнительный метод по имени SquareNumber(), принимающий единственный целочисленный аргумент:public class SimpleMath
{
public static int SquareNumber(int a) => a * a;
}
Учитывая, что делегат BinaryOp
// Ошибка на этапе компиляции! Метод не соответствует шаблону делегата!
BinaryOp b2 = new BinaryOp(SimpleMath.SquareNumber);
Исследование объекта делегата
Давайте усложним текущий пример, создав в классе Program
DisplayDelegatelnfо()). Он будет выводить на консоль имена методов, поддерживаемых объектом делегата, а также имя класса, определяющего метод. Для этого организуется итерация по массиву System.Delegate, возвращенному методом GetlnvocationList(), с обращением к свойствам Target и Method каждого объекта:static void DisplayDelegateInfo(Delegate delObj)
{
// Вывести имена всех членов в списке вызовов делегата.