Новые средства языка. Делегат на основе обычного метода класса. Делегаты на основе класса MulticastDelegate, страница 2

{

Console.WriteLine ("\nI got the exception:\n" + e.Message);

}

Не поленитесь и проверьте работу этого фрагмента (при пустой коллекции). Приятным моментом здесь является та обстоятельность, с которой объект e выводит причину ошибки. Несмотря на это приятное открытие, подобный подход к разработке программ способен привести в уныние любого программиста. Хотя, за всех не скажешь.

Теперь посмотрим, как в аналогичной ситуации поведет себя индексатор. Для этого вновь измените тело функции Main. В ней мы сначала поработаем со списком без явных ошибок, а затем специально обратимся к нему с недопустимыми значениями индекса.

static void Main()

{

object[] goods = { "Bike", "Wife", "Summer House" };

Man alex = new Man ("Alex Black", 56, goods);     // Создадим богатого человека

object o = alex[0];   // Проверим поведение аксессора get

Console.WriteLine(o);

Console.WriteLine("Alex has: {0}, {1}, {2}", alex[0], alex[1], alex[2]);

alex[0] = "New Bike";   // Проверим поведение аксессора set

Console.WriteLine (alex[0]);    // и снова get

}

Для тех, кто не имеет под рукой компьютера с установленной на нем лицензионной версией студии, сообщим, что после запуска приложения в консольном окне события будут развиваться по такому сценарию:

alex[0] = Bike

Alex has: Bike, Wife, Summer House

alex[0] = New Bike

Теперь проверим поведение индексатора в случае некорректного обращения с индексом. Добавьте в конец функции Main такие строки.

   //==== Проверим поведение средств защиты

Console.Write (alex [-1]);// get

alex [2048] = o;          // set

Хорошо то, что приложение не прерывается и реагирует на ошибки вполне адекватным образом. В окне вы видите ту реакцию, которая было заложена нами при создании индексатора.

get: wrong id = -1

set: wrong id = 2048

В заключение обзора возможностей индексатора, отметим, что его применение, например, для класса «многоугольник» было бы более естественным, чем для объектов класса Man. С помощью индексатора мы могли бы простым образом опрашивать или устанавливать координаты произвольной вершины многоугольника.

Синтаксис индексатора напоминает синтаксис свойств, но запомните. Свойство может быть как обычным членом класса, так и статическим. Индексатор же статическим быть не может.

Класс Delegate

Предположим, что мы хотим вывести содержимое списка людей в консольное окно. Действия такого рода удобны для демонстрации нового средства языка, именуемого ключевым словом delegate (делегат). Все делегаты поддержаны классом Delegate из пространства имен System библиотеки .Net Framework. Этот класс является базовым для всех делегатных типов данных. Мы можем пользоваться статическими методами класса, но не можем производить свои классы, наследующие от него. Только система и компилятор пользуется этим классом для создания производных классов. Если мы хотим создать делегата, то должны пользоваться ключевым словом delegate, которое специально для этой цели введено в язык С#.

Делегат имеет известный нам аналог в языке С++. Им является указатель на функцию. Однако делегат в С# — это более сложное понятие. С его помощью можно не только вызвать одну из функций с определенным прототипом, но и запустить цепочку вызовов, то есть последовательно вызвать несколько функций.

Делегат на основе обычного метода класса

В качестве методов, которые будут вызываться делегатами, мы используем два метода класса Man: Firstname и Surname. Если они отсутствуют в классе, то добавьте их. Первый выводит имя человека, а второй фамилию. Например, если name = "Alex Black", то FirstName должен вывести на экран строку Alex, а  SurnameBlack.

Важно, чтобы оба метода имели одинаковую сигнатуру (или прототип). В нашем случае это требование сводится к тому, что обе функции должны быть типа void, то есть ничего не возвращать в точку вызова и обе не должны требовать параметра. После выбора функций, которые будут приписаны делегату, надо объявить делегатный тип в том классе, в котором он будет использоваться. Поместите это объявление в класс ManTest.

public delegate void ManDelegate();

Оно создает новый тип данных — ManDelegate. Объекты этого типа будут созданы позже. Такое объявление задает сигнатуру функции обработки и, в то же время определяет делегатный класс, реализация которого скрыта от нас. Ее берет на себя CLR.