Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
...
}
Делегаты могут также "указывать" на методы, которые содержат любое количество параметров
out
ref
params
public delegate string MyOtherDelegate(out bool a, ref bool b, int c);
Сигнатура метода
Invoke()
Подводя итоги, отметим, что определение типа делегата C# дает в результате запечатанный класс со сгенерированным компилятором методом, в котором типы параметров и возвращаемые типы основаны на объявлении делегата. Базовый шаблон может быть приближенно описан с помощью следующего псевдокода:
// Это лишь псевдокод!
public sealed class <i>ИмяДелегата</i> : System.MulticastDelegate
{
public <i>возвращаемоеЗначениеДелегата</i>
Invoke(<i>всеВходныеRefиOutПараметрыДелегата</i>);
}
Базовые классы System.MulticastDelegate и System.Delegate
Итак, когда вы строите тип с применением ключевого слова
delegate
System.MulticastDelegate
System.MulticastDelegate
public abstract class MulticastDelegate : Delegate
{
<b> // Возвращает список методов, на которые "указывает" делегат.</b>
public sealed override Delegate[] GetInvocationList();
<b> // Перегруженные операции.</b>
public static bool operator ==
(MulticastDelegate d1, MulticastDelegate d2);
public static bool operator !=
(MulticastDelegate d1, MulticastDelegate d2);
<b> // Используются внутренне для управления списком методов,</b>
<b> // поддерживаемых делегатом.</b>
private IntPtr _invocationCount;
private object _invocationList;
}
Класс
System.MulticastDelegate
System.Delegate
public abstract class Delegate : ICloneable, ISerializable
{
<b> // Методы для взаимодействия со списком функций.</b>
public static Delegate Combine(params Delegate[] delegates);
public static Delegate Combine(Delegate a, Delegate b);
public static Delegate Remove(
Delegate source, Delegate value);
public static Delegate RemoveAll(
Delegate source, Delegate value);
<b> // Перегруженные операции.</b>
public static bool operator ==(Delegate d1, Delegate d2);
public static bool operator !=(Delegate d1, Delegate d2);
<b> // Свойства, открывающие доступ к цели делегата.</b>
public MethodInfo Method { get; }
public object Target { get; }
}
Имейте в виду, что вы никогда не сможете напрямую наследовать от таких базовых классов в своем коде (попытка наследования приводит к ошибке на этапе компиляции). Тем не менее, когда вы используете ключевое слово
delegate
MulticastDelegate

Пример простейшего делегата
На первый взгляд делегаты могут показаться несколько запутанными. Рассмотрим для начала простой проект консольного приложения (по имени
SimpleDelegate
BinaryOp
// SimpleMath.cs
namespace SimpleDelegate
{
// Этот класс содержит методы, на которые
// будет указывать BinaryOp.
public class SimpleMath
{
public static int Add(int x, int y) => x + y;
public static int Subtract(int x, int y) => x - y;
}
}
// Program.cs
using System;
using SimpleDelegate;
Console.WriteLine("***** Simple Delegate Example *****n");
<b>// Создать объект делегата BinaryOp, который</b>
<b>// "указывает" на SimpleMath.Add().</b>