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

public ArrayList men;

После этих приготовлений мы можем, создать в классе ManTest метод Show, в котором дадим пользователю возможность выбрать способ вывода информации об объектах, хранимых в списке men. Выбор осуществляется с помощью вспомогательноuj метода ShowMenu.

public char ShowMenu()

{

Console.Write(

"\n\t\tf - First Names"+

"\n\t\ts - Surnames"+

"\n\t\tn - Normal"+

"\n\t\tq - Quit\n\n");

return Console.ReadLine().ToLower()[0];

}

Метод Show содержит:

¨  Инициализацию коллекции людей,

¨  Объявление объекта d делегатного класса ManDelegate

¨  Псевдо-бесконечный цикл, в котором мы даем пользователю возможность выбрать способ вывода информации об объектах, хранимых в списке men.

public void Show()

{

men = new ArrayList();

men.Add (new Man ("Ken Wood",40));

men.Add (new Man ("Lennie Tristano",50));

men.Add (new Man ("Ben Webster",60));

ManDelegate d; //=== Вот он — делегат (объект, который можно вызывать как функцию)

while (true)

{

Console.WriteLine ("\n\nList of men\n\n");

switch (ShowMenu())  // Пользователь выбирает способ вывода информации

{

case 'q':   return; // Закачиваем работу

case 'f':

foreach (Man m in men)

{

d = new ManDelegate (m.Firstname);    // Инициализируем делегата и вызываем как функцию

d();

}

break;

case 's':

foreach (Man m in men)

{

d = new ManDelegate (m.Surname);

d();

}

break;

case 'n':       //===== Выводим список обычным образом

foreach (Man m in men)

Console.WriteLine (m);

break;

}

}

}

Для запуска новой версии проекта вам понадобится изменить код функции Main. Сделайте это самостоятельно.

Test test = new Test();

test.Show();

Затем запустите и выберите нормальный режим демонстрации списка (3-й пункт меню). Убедиттесь в том, что при выводе данных любого объекта надежно работает все тот же полиморфизм позднего связывания. Именно этот механизм позволяет правильно выбрать на этапе выполнения тело виртуальной функции ToString. Затем проверьте функционирование делегатов. При анализе кода обратите внимание на то, что мы создаем новые объекты, являющиеся реальными делегатами (а не просто объявлениями типа). Это происходит в строках:

d = new ManDelegate (m.Firstname);

d = new ManDelegate (m.Surname);

При создании делегаты инициализируются ссылкой на функцию Firstname или Surname. Последние являются методами класса Man. Обратите внимание на то, как мы работаем с объектом d. При его создании — это переменная (d =. . .). При запуске делегатной функции — это функция d(). Такая техника вызывает противоречивые чувства. "Чайники" не замечают ничего странного (их вообще трудно удивить).

Любое объявление делегатного типа означает заключение контракта (похоже на COM, не так ли?), который вводит и закрепляет сигнатуру (в языке С++ мы называли это прототипом) для одного или нескольких методов, которые могут быть использованы делегатами. Если вы объявили переменную делегатного типа, то можете считать, что она ссылается на одну или несколько функций с заданной сигнатурой (прототипом).

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

Делегаты на основе класса MulticastDelegate