Основы C# Урок 32. Делегаты
Сначала пара слов о том, что такое делегаты. В языке программирования могут быть переменные, содержащие значения целого или вещественного типов. С такими типами все вы хорошо знакомы. Так вот, в первом приближении делегаты - это тоже некоторый тип данных. Что же за тип может хранится в делегатах? В делегатах могут хранится функции (вернее указатели на функции). Т. е. переменной типа делегат можно сначала присвоить одну функцию, поработать с ней, а затем присвоить другую функцию. Это все в первом приближении. Теперь несколько подробностей. Во-первых, делегаты бывают разных типов. Тип делегата определяется типов и количеством параметов и типом возвращаемого значения. Это значит, что если, например, делегат типа void и у него только один параметр типа int, то в такой делегат мы можем записать только функцию типа void и с одним единственым параметроам типа int. Во-вторых, делегаты, в отличие от указателей на функции языка C++, предаставляют из себя безопасные типы данных.
Вот пример делегата:
using System; namespace test { //Объявление делегата. delegate float MyFunc(float x); //Класс для тестирования делегата. class Test { //Первая функция. static float f1(float x) { return x; } //Вторая функция. static float f2(float x) { return x*x; } //Третья функция. static float f3(float x) { return (float)Math.Sqrt(x); } //Метод Main. static void Main() { //Создаем экземпляр делегата. MyFunc f = new MyFunc(f1); int a; //Ответ пользователя. Console.WriteLine("Выберите функцию:\n1.f1=x.\n2.f2=x*x.\n3.f3=sqrt(x)."); //Преобразуем ответ пользователя к типу Int32 a=Int32.Parse(Console.ReadLine()); switch(a) { case 1: //Записываем в делегат 1-ю функцию. f=new MyFunc(f1); break; case 2: //Записываем в делегат 2-ю функцию. f=new MyFunc(f2); break; case 3: //Записываем в делегат 3-ю функцию. f=new MyFunc(f3); break; } //Печатаем результат. int x=4; Console.WriteLine("f({0})={1}", x, f(x)); } } }
В этой программе мы сначала объявляем делегат:
... delegate float MyFunc(float x); ...
Синаксис объявления делегата такой - сначала пишем ключевое слово delegate, затем - тип возвращаемого значения (float в нашем примере), потом - произвольное имя делегата (у нас это MyFunc), после которого в круглых скобках перечисляем параметры (у нас только один параметр типа float). Объявленный делегат появится на вкладке ClassView (со специальным значком для делегатов):
Далее мы в нашем тестовом классе объявляем несколько методов - f1, f2 и f3. Все эти методы имеют тип float и один параметр типа float (как и у делегата MyFunc). Функции делают свой подсчет по-разному - первая просто возвращает параметр, вторая - квадрат параметра, третья - корень из параметра.
Далее мы в методе Main создаем экземпляр нашего делегата и в зависимости от ответа пользователя записываем в него f1, f2 или f3. Потом в строке
... Console.WriteLine("f({0})={1}", x, f(x)); ...
мы выводим значение делегата при некотором x (равном 4 в нашем примере). Вернее сказать, мы выводим не значение делегата, а значение функции, которую мы записали в делегат.
В зависимости от ответа пользователя в делегат запишется тот или иной вариант функции и программа выведет сам x (4), x умножить на x (16) или корень из x (2):