Ответ
В C# делегаты — это типобезопасные указатели на методы. Основные виды:
-
Пользовательские делегаты (обычные) — объявляются с ключевым словом
delegate. Используются реже, так как в большинстве случаев их заменяютActionиFunc.delegate int StringToIntConverter(string input); -
Action— предопределённый обобщённый делегат для методов, которые не возвращают значение (возвращаютvoid). Может принимать от 0 до 16 параметров.Action<string> logAction = (message) => Console.WriteLine($"[LOG]: {message}"); Action<int, int> sumAction = (a, b) => Console.WriteLine(a + b); -
Func— предопределённый обобщённый делегат для методов, которые возвращают значение. Последний параметр типа всегда указывает на возвращаемый тип.Func<int, int, int> addFunc = (a, b) => a + b; Func<string, bool> isNotEmptyFunc = (str) => !string.IsNullOrEmpty(str); -
Predicate<T>— специализированный делегат для проверки условия. Возвращаетbool. По сути, это аналогFunc<T, bool>, но с более ясным намерением в коде.Predicate<int> isEvenPredicate = (number) => number % 2 == 0; // Эквивалентно: Func<int, bool> isEvenFunc = ... -
EventHandlerиEventHandler<TEventArgs>— стандартные делегаты для реализации событийной модели.public event EventHandler SomethingHappened; public event EventHandler<FileLoadedEventArgs> FileLoaded;
Почему это важно: Action и Func устраняют необходимость вручную объявлять множество делегатов, делая код чище и более унифицированным. Все делегаты в C# являются мультикаст-делегатами — они могут содержать ссылки на несколько методов и вызывать их по цепочке.
Action multiAction = () => Console.Write("Hello, ");
multiAction += () => Console.WriteLine("World!");
multiAction(); // Выведет: "Hello, World!" Ответ 18+ 🔞
А, делегаты в C#! Ну это ж классика, блядь. Сидишь такой, пишешь код, и тут тебе надо метод в метод передать, как переменную. Ну типобезопасные указатели на методы, если по-умному. Смотри, как оно устроено, а то многие нихуя не понимают.
Во-первых, есть пользовательские делегаты. Объявляешь через delegate, как будто сигнатуру метода описываешь. Раньше это было модно, а сейчас нихуя не нужно, потому что придумали Action и Func. Но для истории, выглядит так:
delegate int StringToIntConverter(string input);
Ну то есть, объявил тип — теперь можешь переменную такого типа завести и в неё любой метод запихнуть, который строку принимает и инт возвращает. Старорежимно, но работает.
А теперь смотри, главные герои — Action и Func. Это предопределённые делегаты, их дохуя видов, и они тебя спасут от писанины кучи своих делегатов.
Action — это для методов, которые нихуя не возвращают, то есть void. Может от нуля до 16 параметров таскать. Примеры, чтобы понятно было:
Action<string> logAction = (message) => Console.WriteLine($"[LOG]: {message}");
Action<int, int> sumAction = (a, b) => Console.WriteLine(a + b);
Первый — принимает строку и пишет в консоль. Второй — два инта принимает, сумму выводит. Возвращает void, поэтому Action. Всё просто, ёпта.
Func — а вот это уже для методов, которые что-то возвращают. Последний параметр типа — это всегда возвращаемый тип, запомни это, а то запутаешься. Пример:
Func<int, int, int> addFunc = (a, b) => a + b;
Func<string, bool> isNotEmptyFunc = (str) => !string.IsNullOrEmpty(str);
Видишь? Func<int, int, int> — первые два инта это параметры, последний — что возвращает. Строку принял — bool вернул. Красота, блядь.
Ещё есть Predicate<T> — это такой специальный олдскульный делегат для проверки условий. Возвращает bool, по сути то же самое, что Func<T, bool>, но название намекает, что тут будет какое-то условие. Чисто для читаемости, понимаешь?
Predicate<int> isEvenPredicate = (number) => number % 2 == 0;
// То же самое, что: Func<int, bool> isEvenFunc = ...
Ну и куда же без событий! Для них есть EventHandler и EventHandler<TEventArgs>. Это стандартные делегаты, на них завязана вся событийная модель в C#. Без них никуда, если пишешь что-то с событиями.
public event EventHandler SomethingHappened;
public event EventHandler<FileLoadedEventArgs> FileLoaded;
И главная фишка, которую многие забывают: все делегаты в C# — мультикаст-делегаты. Это значит, что в одну переменную можно навешать кучу методов, и они вызовутся по цепочке. Смотри, как прикольно:
Action multiAction = () => Console.Write("Hello, ");
multiAction += () => Console.WriteLine("World!");
multiAction(); // Выведет: "Hello, World!"
Два метода в одну кучу, и оба сработали. Вот так вот, блядь. Action и Func — это пиздец как удобно, потому что не надо каждый раз свой делегат объявлять. Бери и пользуйся, как конструктор. Главное — не перепутай, где void, а где нет, а то получишь ошибку, и будешь сидеть, чесать репу.
Видео-ответы
▶
▶
▶
▶
▶
▶