Четверг, 25.04.2024, 23:11
Приветствую Вас Гость | RSS

Лекции

Меню сайта
Форма входа
Категории раздела
ТАУ (Теория автоматического управления) [31]
лекции по ТАУ
Экология [151]
учебник
Бухгалтерский учет и налогообложение в строительстве [56]
Дементьев А.Ю. - Практическое пособие
Психология [104]
Пип
информатика [80]
с# Карли Ватсон
современные стулья [0]
новинки
Поиск

Главная » 2010 » Февраль » 11 » Делегаты
00:18
Делегаты
Делегаты
Делегатом называется тип, который позволяет хранить ссылки на функции.
Несмотря на то что звучит это несколько интригующе, механизм, лежащий в основе
этой возможности, удивительно прост. Наиглавнейшее предназначение делегатов
вряд ли удастся понять до тех пор, пока вы не познакомитесь с событиями и с их
обработкой, однако рассмотрение самого понятия делегатов принесет огромную
пользу. Когда позднее наступит время их использовать, они будут вам уже знако-
мы, что сделает некоторые сложные темы гораздо более легкими для понимания.
Объявление делегатов во многом напоминает объявление функций; при этом
отсутствует само тело функции, но добавляется ключевое слово delegate. Объяв-
ление делегата определяет сигнатуру функции, состоящую из возвращаемого типа
и списка параметров. После объявления делегата мы получаем возможность объя-
вить переменную типа этого делегата. Мы можем затем инициализировать эту
переменную, присвоив ей ссылку на произвольную функцию, обладающую сигна-
турой, совпадающей с сигнатурой делегата. После всего этого мы получаем воз-
можность вызывать эту самую функцию с помощью данной переменной-делегата
так, как если бы последняя сама являлась этой функцией.
Теперь, когда у нас имеется переменная, ссылающаяся на функцию, мы также
получаем возможность выполнять и некоторые другие операции, которые не могут
быть выполнены с использованием иных средств. Например, появляется возмож-
ность передавать переменную-делегат другой функции в качестве параметра, что
позволит этой функции использовать данного делегата для вызова функции, на ко-
торую он ссылается, без необходимости определять вызываемую функцию до начала
выполнения программы. Давайте рассмотрим пример.
Функции 129
Практикум: использование делегата для вызова функции
1. Создайте новое консольное приложение с именем chO6ExO5
В директории C:\BegCSharp\Chapter6.
2. Добавьте следующий код в ciassi.cs:
class Classl
Н Р Т Р Г Г Л Г Р rtnnhi р П Г П Г Р Я Я Л Р ! p n f l t p f r i n n h l р п л г я т 1 . Н п п Ы Р п я г л т Л :
static double Multiply(double paraml, double param2)
return paraml * param2;
static double Divide(double paraml, double param2)
return paraml / param2;
}
static void Main (string [] args)
processDelegate process;
Console.WriteLine("Enter 2 numbers separated with a comma:*);
string input = Console.ReadLine();
int commaPos = input.IndexOf{',');
double paraml,= Convert.ToDouble(input.Substring(0, commaPos)) ;
double param2 = Convert.ToDouble(input.Substring(commaPos + 1,
input.Length - commaPos - 1)) ;
Console.WriteLine("Enter M to multiply or D to divide:*);
input = Console.ReadLine();
if (input == «M")
process = new processDelegate(Multiply);
else
process = new processDelegate(Divide);
Console.WriteLine("Result: {0}", process(paraml, param2));
3. Запустите программу:
EjC\BegCSharp\Chapl:er6\Ch06EK05\bin\l>
Enter 2 numbers separated uxth а cororaa
7.2.6.3
Enter Ш to Multiply oi» D to divide"
П
Result: 45«36
Press any he^ to cosntioue
Ш
Как это работает
Этот код описывает делегата (processDelegate), сигнатура которого совпадает
с сигнатурой двух функций: Multiply о и Divide*). Делегат имеет следующее
определение:
delegate double processDelegate (double paraml, double param2) ;
Ключевое слово delegate указывает, что данное определение является опреде-
лением делегата, а не функции (это определение располагается в том же месте
130 Глава 6
программы, где могло бы находиться и определение функции). Далее приводится
сигнатура, в которой задаются возвращаемое значение типа double и два параметра
типа double. Используемые в сигнатуре имена являются произвольными, поэтому
тип делегата и имена параметров мы можем выбирать по своему усмотрению.
В данном случае мы выбрали имя делегата processDeiegate, а параметры назвали
paraml И param2.
Код функции Main о начинается с того, что мы объявляем переменную, восполь-
зовавшись описанным типом делегата:
static void Main (string [] args)
{
processDeiegate process;
Затем следует абсолютно стандартный для С# код, который запрашивает два чис-
ла, разделенные запятой, и присваивает их двум переменным типа double:
Console.WriteLine('Enter 2 numbers separated with a comma:*);
string input = Console.ReadLineO ;
int commaPos = input.IndexOf(',');
double paraml = Convert.ToDouble(input.Substring(0, commaPos));
double param2 = Convert .ToDouble (input. Substring (commaPos + 1,
input.Length - commaPos - 1) ) ;
Обратите внимание, что для наглядности в программу
не включены никакие проверки допустимости
вводимой пользователем информации. В реальной программе
нам пришлось бы потратить большое количество времени,
проверяя допустимость тех значений, которые мы получаем
для ЛОКаЛЬНЫХ Переменных paraml U param2.
Затем мы запрашиваем пользователя, следует ли умножать или делить эти числа:
Console.WriteLine('Enter M to multiply or D to divide:*);
input = Console.ReadLine();
В зависимости от полученного ответа мы инициализируем переменную-делегат:
if (input == "М")
process = new processDeiegate(Multiply);
else
process = new processDeiegate(Divide);
Для присвоения переменной-делегату ссылки на функцию нам приходится ис-
пользовать несколько странно выглядящий синтаксис. Так же, как и в случае при-
сваивания значений массиву, для создания нового делегата используется ключевое
слово new. После этого слова указывается тип создаваемого делегата и задается
параметр, определяющий ту функцию, которую мы хотим использовать, а именно
функцию console.writeLineO. Обратите внимание, что этот параметр не совпа-
дает ни с параметрами типа делегата, ни с параметрами используемой функции:
это уникальный синтаксис, применяемый исключительно для осуществления при-
сваивания делегату. В качестве параметра используется просто имя той функции,
которую необходимо использовать, без скобок.
Наконец, мы вызываем выбранную нами функцию с помощью делегата. Здесь
применяется один и тот же синтаксис, независимо от того, на какую именно функ-
цию ссылается делегат:
Console.WriteLine('Result: {0}*, process(paraml, param2));
Функции 131
В данном случае мы обращаемся с переменной-делегатом так, как если бы она
представляла собой имя функции. Однако, в отличие от функций, над этой пере-
менной можно выполнять некоторые дополнительные операции, например, переда-
чу ее другой функции в качестве параметра. Простой пример такого использования
может выглядеть примерно следующим образом:
static void executeFunction(processDelegate process)
•; {
process(2.2, 3.3);
} ..*•' , :Ш.
Это означает, что мы получаем возможность управлять поведением функций,
передавая им в качестве параметров делегатов функций, что во многом напоминает
выбор используемого (snap-in). Например, может иметься функция, используемая
для сортировки строкового массива по алфавиту. Существуют различные алгорит-
мы сортировки списков, обладающие различным быстродействием, что зависит от
характеристик сортируемого списка. С помощью делегатов мы получаем возмож-
ность определять метод, который необходимо использовать, передавая функции,
выполняющей сортировку, делегата той функции, в которой реализован соответст-
вующий алгоритм сортировки.
Вариантов применения делегатов существует очень много, но, как отмечалось
выше, наиболее плодотворно они используются при обработке событий. Мы будем
обсуждать эту тему в главе 12.
Итоги
В данной главе был сделан достаточно полный обзор использования функций
в программе на С#. Большая часть дополнительных возможностей, предоставляемых
функциями (в частности, использование делегатов), являются достаточно абстракт-
ными, и их необходимо обсуждать только с точки зрения объектно-ориентированного
программирования, к рассмотрению которого мы вскоре перейдем.
Подведем итоги темам, которые обсуждались в данной главе:
• Определение и использование функций
в консольных приложениях
• Обмен данными с функциями посредством параметров
и возвращаемых значений
• Массивы параметров
• Передача параметров по ссылке и по значению
• Использование выходных параметров
для дополнительных возвращаемых значений
• Понятие области действия переменной
• Особенности функции Main (), в том числе
использование параметров командной строки
• Использование функций в типах структур
• Перегрузка функций
• Делегаты
132
Упражнения
1. В следующих двух функциях содержатся ошибки. Какие именно?
s t a t i c bool Write()
Console.WriteLine(*Text output from function.");
s t a t i c void myFunction(string label, params i n t [ ] args, bool showLabel)
i f (showLabel)
Console.WriteLine(label);
foreach {int i in args) : • •/. ' . .
Console.WriteLine("{О}*, x) ; • :
2. Напишите приложение, которое использует два аргумента
командной строки для присваивания значений строковой и целой
переменным соответственно, а затем выводит эти значения.
3. Создайте делегата и используйте его вместо
функции Console.ReadLineо в запросе ввода от пользователя.
4. Модифицируйте приведенную ниже структуру, включив в нее
функцию, которая возвращает суммарную стоимость заказа:
struct order // заказ //
public string iteraName; // наименование //
public int unitCount; // число единиц //
public double unitCost; // стоимость одной единиц
































Категория: информатика | Просмотров: 1400 | Добавил: basic | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Календарь
«  Февраль 2010  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

krutoto.ucoz.ru
Бесплатный конструктор сайтов - uCoz