English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Если мы хотим передавать функцию в качестве параметра, что делать? Как C# обрабатывает обратные вызовы или обработчики событий? Ответ - делегат (Delegate). Делегат (Delegate) - это тип переменной, которая хранит ссылку на метод. Ссылка может быть изменена в режиме выполнения.
Делегат являетсяопределение подписи методатип данных по ссылке. Вы можете определить переменную делегата, как и другие типы данных, которые могут ссылаться на любой метод с подписью, совпадающей с подписью делегата.
Работа с делегатами включает три шага:
Объявление делегата
Установка целевого метода
Вызов делегата
Делегат можно объявить с помощью ключевого слова delegate и подписи функции, как показано ниже.
Синтаксис делегата
[доступ] delegate [возвращаемый тип] [имя делегата]([параметры])
Ниже приведена декларация делегата под названием MyDelegate.
public delegate void MyDelegate(string msg);
Ниже мы объявили MyDelegate с
После объявления делегата нам нужно установить целевой метод или lambda-выражение. Это можно сделать, создав объект делегата с помощью ключевого слова new и передав метод, подпись которого соответствует подписи делегата.
public delegate void MyDelegate(string msg); // декларация делегата // установление целевого метода MyDelegate del = new MyDelegate(MethodA); // или MyDelegate del = MethodA; // или lambda-выражение MyDelegate del = (string msg) => Console.WriteLine(msg); // целевой метод static void MethodA(string message) { Console.WriteLine(message); {}
Целевой метод можно установить напрямую, не создавая объекта делегата, например, MyDelegate del = MethodA.
После установки целевого метода можно использовать метод Invoke() или использовать оператор () для вызова делегата.
del.Invoke("Hello World!"); // или del("Hello World!");
Ниже приведен полный пример делегата.
public delegate void MyDelegate(string msg); // Объявление делегата class Program { static void Main(string[] args) { MyDelegate del = ClassA.MethodA; del("Hello World"); del = ClassB.MethodB; del("Hello World"); del = (string msg) => Console.WriteLine("Called lambda expression: " + msg); del("Hello World"); {} {} class ClassA { static void MethodA(string message) { Console.WriteLine("Called ClassA.MethodA() with parameter: " + message); {} {} class ClassB { static void MethodB(string message) { Console.WriteLine("Called ClassB.MethodB() with parameter: " + message); {} {}
На следующем рисунке показан делегат.
Метод может иметь параметр типа делегата, как показано ниже.
public delegate void MyDelegate(string msg); // Объявление делегата class Program { static void Main(string[] args) { MyDelegate del = ClassA.MethodA; InvokeDelegate(del); del = ClassB.MethodB; InvokeDelegate(del); del = (string msg) => Console.WriteLine("Called lambda expression: " + msg); InvokeDelegate(del); {} static void InvokeDelegate(MyDelegate del) // Параметр типа MyDelegate { del("Hello World"); {} {} class ClassA { static void MethodA(string message) { Console.WriteLine("Called ClassA.MethodA() with parameter: " + message); {} {} class ClassB { static void MethodB(string message) { Console.WriteLine("Called ClassB.MethodB() with parameter: " + message); {} {}
В .NET типы Func и Action являются вbuilt-генерическими делегатами и должны использоваться для наиболее распространённых делегатов, а не для создания новых пользовательских делегатов.
Делегаты могут указывать на несколько методов. Делегаты, указывающие на несколько методов, называются multicast delegate. Операторы '+' или '+=' добавляют функцию в список вызовов, а операторы '-' и '-=' удаляют её.
public delegate void MyDelegate(string msg); // Объявление делегата class Program { static void Main(string[] args) { MyDelegate del1 = ClassA.MethodA; MyDelegate del2 = ClassB.MethodB; MyDelegate del = del1 + del2; // del1 + del2 del("Hello World"); MyDelegate del3 = (string msg) => Console.WriteLine("Called lambda expression: " + msg); del += del3; // del1 + del2 + del3 del("Hello World"); del = del - del2; // Удалить del2 del("Hello World"); del -= del1 // Удалить del1 del("Hello World"); {} {} class ClassA { static void MethodA(string message) { Console.WriteLine("Called ClassA.MethodA() with parameter: " + message); {} {} class ClassB { static void MethodB(string message) { Console.WriteLine("Called ClassB.MethodB() with parameter: " + message); {} {}
Операторы сложения и вычитания всегда работают как часть присваивания: del1 += del2; это эквивалентно del1 = del1 + del2; также и с вычитанием.
Если делегат возвращает значение, то при вызове multicast делегата возвращается значение последнего распределенного метода.
public delegate int MyDelegate(); // объявление делегата class Program { static void Main(string[] args) { MyDelegate del1 = ClassA.MethodA; MyDelegate del2 = ClassB.MethodB; MyDelegate del = del1 + del2; Console.WriteLine(del());// возвращается 200 {} {} class ClassA { static int MethodA() { return 100; {} {} class ClassB { static int MethodB() { return 200; {} {}
Генерические делегаты можно определить так же, как и делегаты, но можно использовать генерические типы параметров или возвращаемого типа. При установке цели метода необходимо указать генерический тип.
Например, посмотрите на общие делегаты для параметров int и string.
public delegate T add<T>(T param1, T param2); // генерический делегат class Program { static void Main(string[] args) { add<int> sum = Sum; Console.WriteLine(sum(10, 20)); add<string> con = Concat; Console.WriteLine(conct("Hello", "World!!")); {} public static int Sum(int val1, int val2) { return val1 + val2; {} public static string Concat(string str1, string str2) { return str1 + str2; {} {}
Делегаты также используются для объявления событий и анонимных методов.
Делегат - это тип данных, представляющий собой ссылку на подпись.
Переменная типа делегата может ссылаться на любое метод, имеющее такую же подпись, как и делегат.
Грамматика:[Доступ修饰итель] делегат [возвратный тип] [имя делегата]([параметры])([access modifier] delegate [return type] [delegate name]([parameters]))
Подпись метода цели должно соответствовать подписи делегата.
Делегаты могут быть вызваны так же, как и обычные функции или invoke() метод.
Множественные методы могут быть добавлены к делегату с помощью операторов '+' или '+=', и удалены с помощью операторов '-' или '-=', что называется многопоточными делегатами.
Если многопоточность делегата возвращает значение, то оно возвращается из последнего назначения метода.
Делегаты используются для объявления событий и анонимных методов в C#.