Какие знаешь делегаты


В C# делегаты — это тип, который представляет ссылку на метод с определённой сигнатурой. Они позволяют передавать методы как параметры, вызывать их асинхронно, комбинировать в цепочки, использовать как обработчики событий и основу для функционального программирования. Делегаты — мощный инструмент инкапсуляции поведения.

🔹 Виды делегатов, которые стоит знать:

1. Обычные (пользовательские) делегаты

Это делегаты, определяемые вручную:

public delegate int Operation(int a, int b); // сигнатура: (int, int) -> int
Operation op = Add;
int result = op(2, 3); // вызывает метод Add
int Add(int a, int b) => a + b;

2. Multicast-делегаты

Это делегаты, которые могут содержать несколько методов в цепочке. Все методы вызываются по порядку, но возвращается результат только последнего.

public delegate void Notify();
Notify notify = Method1;
notify += Method2;
notify(); // вызовет сначала Method1, затем Method2

3. Обобщённые делегаты — Func, Action, Predicate

Чтобы не создавать собственные типы делегатов каждый раз, используются встроенные обобщённые делегаты:

🔸 Func<...> — для методов, возвращающих значение

Сигнатура:

Func&lt;T1, T2, ..., TResult&gt;
Func&lt;int, int, int&gt; sum = (a, b) => a + b;
int result = sum(3, 5); // 8

Если без параметров:

Func&lt;string&gt; greet = () => "Hello";
#### **🔸 Action&lt;...&gt; — для методов без возвращаемого значения**

Сигнатура:

Action&lt;T1, T2, ..., Tn&gt;
Action&lt;string&gt; print = s => Console.WriteLine(s);
print("Привет!");

🔸 Predicate<T> — для булевых условий

Сигнатура:

Predicate&lt;T&gt;  это то же самое, что Func&lt;T, bool&gt;
Predicate&lt;int&gt; isPositive = x => x > 0;
bool result = isPositive(5); // true

🔹 Делегаты и события

События (event) используют делегаты как механизм уведомления:

public delegate void Notify();
public class Process
{
public event Notify Completed;
public void Start()
{
// что-то делаем
Completed?.Invoke(); // вызываем всех подписчиков
}
}

🔹 Асинхронные делегаты

Делегаты можно вызывать асинхронно:

Func&lt;int, int, int&gt; calc = (a, b) => a + b;
IAsyncResult result = calc.BeginInvoke(3, 4, null, null);
// ...
int res = calc.EndInvoke(result);

Но чаще сегодня используют async и Task.

🔹 Делегаты как параметры

Делегаты можно передавать в методы для задания поведения:

void ProcessList(List&lt;int&gt; list, Func&lt;int, bool&gt; filter)
{
foreach (var item in list.Where(filter))
Console.WriteLine(item);
}
ProcessList(new List&lt;int&gt; {1,2,3,4}, x => x % 2 == 0); // фильтруем чётные

🔹 Делегаты и лямбда-выражения

Делегаты отлично сочетаются с лямбдами:

Func&lt;int, int&gt; square = x => x \* x;

или с методами:

Action&lt;string&gt; log = Console.WriteLine;

🔹 Примеры сигнатур:

Делегат Назначение Пример сигнатуры
Action Без параметров и без возвращаемого Action a = () =>
--- --- ---
Action<T> Один параметр, без возвращаемого Action<int> a = x =>
--- --- ---
Func<TResult> Без параметров, но возвращает результат Func<int> f = () => 5
--- --- ---
Func<T, TResult> Один параметр, возвращает результат Func<int, int> f = x => x * x
--- --- ---
Predicate<T> Один параметр, возвращает bool Predicate<string> p = s => s != null
--- --- ---

🔹 Краткое сравнение:

Делегат Параметры Возвращает Для чего используется
Action Есть void Выполнение действий
--- --- --- ---
Func Есть Любой тип Вычисления, функции
--- --- --- ---
Predicate 1 bool Фильтрация, проверки
--- --- --- ---

🔹 Где применяются делегаты:

  • **События и подписчики
    **
  • LINQ (Where, Select, Aggregate и т.п.)

  • Фреймворки и **библиотеки
    **

  • Кастомизация поведения: передача логики через параметры

  • UI обработчики (например, кнопки)

Делегаты делают C# гибким и мощным языком, особенно в сочетании с лямбда-выражениями, функциональным стилем и событиями.