Язык программирования C#9 и платформа .NET5. Страница 236
BinaryOp b = new BinaryOp(SimpleMath.Add);<b>// Вызвать метод Add() косвенно с использованием объекта делегата.</b>Console.WriteLine("10 + 10 is {0}", b(10, 10));Console.ReadLine();// Дополнительные определения типов должны находиться// в конце операторов верхнего уровня.// Этот делегат может указывать на любой метод,// принимающий два целых числа и возвращающий целое число.public delegate int BinaryOp(int x, int y);На заметку! Вспомните из главы 3, что дополнительные определения типов (делегат
BinaryOpИ снова обратите внимание на формат объявления типа делегата
BinaryOpBinaryOpSimpleMathinaryOpКогда вы хотите присвоить целевой метод заданному объекту делегата, просто передайте имя нужного метода конструктору делегата:
// Создать объект делегата BinaryOp, который// "указывает" на SimpleMath.Add().BinaryOp b = new BinaryOp(SimpleMath.Add);На данной стадии метод, на который указывает делегат, можно вызывать с использованием синтаксиса, выглядящего подобным прямому вызову функции:
// На самом деле здесь вызывается метод Invoke()!Console.WriteLine("10 + 10 is {0}", b(10, 10));"За кулисами" исполняющая среда вызывает сгенерированный компилятором метод
Invoke()MulticastDelegateildasm.exeMain().method private hidebysig static void Main(string[] args) cil managed{ ... callvirt instance int32 BinaryOp::Invoke(int32, int32)}Язык C# вовсе не требует явного вызова метода
Invoke()BinaryOpConsole.WriteLine("10 + 10 is {0}", b.Invoke(10, 10));Вспомните, что делегаты .NET Core безопасны в отношении типов. Следовательно, если вы попытаетесь передать делегату метод, который не соответствует его шаблону, то получите ошибку на этапе компиляции. В целях иллюстрации предположим, что в классе
SimpleMathSquareNumber()public class SimpleMath{ public static int SquareNumber(int a) => a * a;}Учитывая, что делегат
BinaryOp// Ошибка на этапе компиляции! Метод не соответствует шаблону делегата!BinaryOp b2 = new BinaryOp(SimpleMath.SquareNumber);Исследование объекта делегата
Давайте усложним текущий пример, создав в классе
ProgramDisplayDelegatelnfо()System.DelegateGetlnvocationList()TargetMethodstatic void DisplayDelegateInfo(Delegate delObj){ // Вывести имена всех членов в списке вызовов делегата. foreach (Delegate d in delObj.GetInvocationList()) { Console.WriteLine("Method Name: {0}", d.Method); // имя метода Console.WriteLine("Type Name: {0}", d.Target); // имя типа }}Предполагая, что в метод
Main()BinaryOp b = new BinaryOp(SimpleMath.Add);DisplayDelegateInfo(b);вывод приложения будет таким:
***** Simple Delegate Example *****Method Name: Int32 Add(Int32, Int32)Type Name:10 + 10 is 20Обратите внимание, что при обращении к свойству
TargetSimpleMathBinaryOpAdd()Substract()staticSimpleMat