Какие знаешь делегаты
В 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<T1, T2, ..., TResult>
Func<int, int, int> sum = (a, b) => a + b;
int result = sum(3, 5); // 8
Если без параметров:
Func<string> greet = () => "Hello";
#### **🔸 Action<...> — для методов без возвращаемого значения**
Сигнатура:
Action<T1, T2, ..., Tn>
Action<string> print = s => Console.WriteLine(s);
print("Привет!");
🔸 Predicate<T> — для булевых условий
Сигнатура:
Predicate<T> — это то же самое, что Func<T, bool>
Predicate<int> 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<int, int, int> calc = (a, b) => a + b;
IAsyncResult result = calc.BeginInvoke(3, 4, null, null);
// ...
int res = calc.EndInvoke(result);
Но чаще сегодня используют async и Task.
🔹 Делегаты как параметры
Делегаты можно передавать в методы для задания поведения:
void ProcessList(List<int> list, Func<int, bool> filter)
{
foreach (var item in list.Where(filter))
Console.WriteLine(item);
}
ProcessList(new List<int> {1,2,3,4}, x => x % 2 == 0); // фильтруем чётные
🔹 Делегаты и лямбда-выражения
Делегаты отлично сочетаются с лямбдами:
Func<int, int> square = x => x \* x;
или с методами:
Action<string> 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# гибким и мощным языком, особенно в сочетании с лямбда-выражениями, функциональным стилем и событиями.