Из предыдущей статьи вы узнали, как создавать определенные типы делегатов с помощью ключевого слова delegate.
Абстрактный класс делегата предоставляет инфраструктуру для слабой взаимозависимости (loose coupling) и вызовов. Конкретные типы делегата становятся гораздо полезнее, поскольку включают и обеспечивают безопасность типов для методов, добавляемых в список вызовов для объекта делегата. Компилятор создает эти методы, если вы используете ключевое слово delegate и определяете конкретный тип делегата.
В результате новые типы делегатов создаются всякий раз, когда возникает необходимость в новой сигнатуре метода. Со временем эта работа может стать слишком громоздкой. Для каждого нового компонента требуются новые типы делегатов.
К счастью, это необязательно. Платформа .NET Core содержит несколько типов, которые можно использовать всякий раз, когда вам нужно делегировать типы. Эти определения универсальны, поэтому всякий раз, когда вам нужно объявить новый метод, можно объявить настройку.
Первый из этих типов — это тип Action и несколько вариантов:
C#
publicdelegatevoidAction();
publicdelegatevoid Action<in T>(T arg);
publicdelegatevoid Action<in T1, in T2>(T1 arg1, T2 arg2);
// Other variations removed for brevity.
Модификатор in для аргумента универсального типа рассматривается в статье о ковариации.
Существуют варианты делегата Action, содержащие до 16 аргументов, такие как Action<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>.
Очень важно, чтобы для каждого из аргументов делегата в этих определениях использовались универсальные аргументы — это дает максимальную гибкость. Аргументы метода могут быть одного типа, однако это необязательно.
В качестве типа делегата используйте один из типов Action с типом возвращаемого значения void.
Платформа включает также несколько типов универсальных делегатов, которые можно использовать в качестве типов делегатов, возвращающих значения:
C#
publicdelegate TResult Func<out TResult>();
publicdelegate TResult Func<in T1, out TResult>(T1 arg);
publicdelegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
// Other variations removed for brevity
Модификатор out для аргумента универсального типа результата рассматривается в статье о ковариации.
Можно подумать, что два эти типа эквивалентны. Это не так.
Эти две переменные не заменяют друг друга. Переменную одного типа нельзя назначить другому типу. В системе типов C# используются имена определенных типов, а не структуры.
Все эти определения типов делегатов в библиотеке .NET Core должны означать, что новый тип делегата для каждой создаваемой функции, которой требуются делегаты, создавать не нужно. Эти универсальные определения должны предоставлять типы делегатов, необходимые в большинстве ситуаций. Можно просто создать экземпляр одного из этих типов с необходимыми параметрами типа. Если алгоритмы можно сделать универсальными, эти делегаты можно использовать как универсальные типы.
Это позволит сэкономить время и свести к минимуму число новых типов, которые нужно создать для работы с делегатами.
В следующей статье представлено несколько общих шаблонов для работы с делегатами на практике.
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Отзыв о .NET
.NET — это проект с открытым исходным кодом. Выберите ссылку, чтобы оставить отзыв:
Присоединитесь к серии встреч для создания масштабируемых решений искусственного интеллекта на основе реальных вариантов использования с другими разработчиками и экспертами.