Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Возвращаемые значения и обработчики событий

...

...

Set

Get

Public class Connection

Namespace Chl2ExO3

Get

Public string Message

Public class MessageArrivedEventArgs: EventArgs

Namespace Chl2Ex03

Многоцелевые обработчики событий

Сигнатура, используемая для события Timer.Elapsed, содержит два параметра, тип которых очень часто встречается в различных обработчиках событий. Вот эти параметры:

• object source — ссылка на объект, который вызвал наступление события

• ElapsedEventArgs e — параметры, передаваемые событием

Причина, по которой в данном событии — да и во многих других событиях тоже — используется параметр типа object, заключается в том, что очень часто необходимо использовать один и тот же обработчик событий для обработки нескольких одинаковых событий, генерируемых различными объектами, и при этом отличать, каким именно объектом сгенерировано данное событие.

Чтобы пояснить и проиллюстрировать это, следует несколько расширить предыдущий пример.: Использование многоцелевого обработчика событий

1. Создайте новое консольное приложение с именем chi2ExO3 в директории C:\BegCSharp\Chapterl2\.

2. Скопируйте код в файлы Classl.cs, Connection.cs и Display.cs из соответствующих файлов в chi2ExO2 и убедитесь в том, что во всех файлах изменены пространства имен с Сh12ExO2 на Сh12ExO3.

3. Добавьте новый класс — MessageArrivedEventArgs, который находится в файле MessageArrivedEventArgs.cs:

using System;

{

{

private string message;

{

{

return message;

}

}

public MessageArrivedEventArgs()

{

message = “No message sent.”;

}

public MessageArrivedEventArgs(string newMessage)

{

message = newMessage

}

}

}

4. Внесите следующие изменения в файл Connection.cs:

{

public delegate void MessageHandler(Connection source,

MessageArrivedEventArgs e);

{

public event MessageHandler MessageArrived;

private string name;

public string name;

{

{

return name;

}

{

name = value;

}

}

private void CheckForMessage(object source, EventArgs e)

{

Console.WriteLine(“Checking for new messages.”);

Random random = new Random ();

if ((random. Next (9) == 0) && (MessageArrived!=null))

{

MessageArrived(this, new MessageArrivedEventArgs(“Hello Mum!”));

}

}

}

}

5. Внесите следующие изменения в файл Display.cs:

public void DisplayMessage(Connection source, MessageArrivedEventArgs e)

{

Console.WriteLine(“Message arrived from: (0)”, source.Name);

Console.WriteLine(“Message Text: (0)”, e.Message);

}

6. Внесите следующие изменения в файл Class1.cs:

static void Main (string [] args)

{

Connection myConnection2 = new Connection ();

myConnection1.Name = “First connection.”;

Connection myConnection2 = new Connection ();

myConnection2.Name = “Second connection.”;

Display myDisplay = new Display();

myConnection1.MessageArrived +=

new MessageHandler(myDisplay.DisplayMessage);

myConnection1.Connect();

myConnection2.Connect();

Console.ReadLine();

}

7. Запустите приложение.

 

 

Как это работает

Передавая ссылку на объект, который вызвал наступление события в качестве одного из параметров обработчика событий, мы получаем возможность настраивать реакцию обработчика событий на конкретные объекты. Эта ссылка обеспечивает возможность доступа к исходному объекту, включая его свойства.

Передавая параметры, содержащиеся в классе, который наследуется от System.EventArgs (как, например, ElapsedEventArgs), мы получаем возможность передавать в качестве параметров (как, например, параметр Message в классе MessageArrivedEventArgs) любую дополнительную информацию.

Кроме того, такие параметры позволяют использовать преимущество полиморфизма. Можно было бы определить обработчик события MessageArrived следующим способом:

public void DisplayMessage(object source, EventArgs e)

{

Console.WriteLine(“Message arrived from: (0)”,

((Connection)source).Name);

Console.WriteLine(“Message Text: (0)”,

((MessageArrivedEventArgs)e).Message);

}

 

и видоизменить определение делегата в файле connection.cs таким образом:

public delegate void MessageHandler(object source, EventArgs e);

Приложение будет выполняться в точности так же, как оно выполнялось и ранее, однако в этом случае функция DisplayMessage () стала более гибкой (по крайней мере в теории — для получения естественного продукта потребуется дополнительная реализация). Тот же самый обработчик событий мог бы работать и с другими событиями, такими как Timer.Elapsed. Хотя для этого потребуется внести некоторые дополнительные изменения в тело обработчика, которые позволят ему должным образом обрабатывать параметры, передаваемые при наступлении события (в результате приведения их типа к типу Объектов Connection и MessageArrivedEventArgs в данном случае возникнет исключительная ситуация и вместо этого следует использовать оператор as).

Прежде чем продолжить движение вперед, следует обратить внимание на то, что результатом выполнения данного примера будут, скорее всего, пары событий, сгенерированных двумя объектами Сonnection. Такая ситуация возникает благодаря способу, с помощью которого происходит генерация случайных чисел классом Random. В момент создания экземпляра объекта типа Random используется некоторое начальное значение. Оно применяется для получения последовательности псевдослучайных чисел с помощью некоторой сложной функции. (Компьютеры не имеют возможности создавать действительно случайные числа.) Можно задавать начальное значение в конструкторе экземпляра Random, однако если он не используется (как в настоящем примере), то в качестве начального значения используется текущее время. Поскольку мы создаем экземпляры и начинаем использовать оба наших объекта Сonnection в последовательных строках кода, то это с большой вероятностью может привести к тому, что при реакции на наступление событий Timer.Elapsed ими будут использоваться одни и те же начальные значения, поэтому в том случае, когда один из объектов отправляет свое сообщение, второй, вероятнее всего, будет отправлять свое. Это прямое следствие высокой скорости обработки инструкций, и, для того чтобы обойти эту ситуацию, необходимо задавать начальные значения каким-то другим способом. Одно из возможных решений, которое здесь не будет реализовываться, заключается в том, чтобы использовать единственный экземпляр класса Random, доступный из обоих объектов Connection.

В таком случае оба этих объекта будут использовать одну и ту же последовательность случайных чисел, поэтому одновременная отправка сообщений окажется маловероятной.

Все обработчики событий, рассматриваемые до настоящего момента, обладали возвращаемым типом void. Существует возможность задавать для события тип возвращаемого значения, однако это может привести к некоторым проблемам, которые связаны с тем, что наступление некоторого события может приводить к вызову нескольких обработчиков. Если каждый из вызванных обработчиков будет возвращать какое-либо значение, то становится непонятным, какое именно возвращаемое значение будет получено.

В системе эта проблема решается таким образом, что доступным оказывается только последнее возвращаемое обработчиком значение, и это будет значение, возвращаемое обработчиком, который последним подписался на данное событие.

Вероятно, существуют ситуации, когда такая функциональная возможность окажется полезной, хотя авторам так и не удалось придумать ни одной такой ситуации. Рекомендуется использовать обработчики событий типа void и избегать параметры типа out.

<== предыдущая лекция | следующая лекция ==>
Public class Display | Клиентская программа карточной игры для CardLib
Поделиться с друзьями:


Дата добавления: 2014-01-04; Просмотров: 352; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.015 сек.