Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка для КР по ООП.doc
Скачиваний:
8
Добавлен:
18.04.2019
Размер:
2.47 Mб
Скачать

События

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

Класс, содержащий объявление события поддерживает:

  • регистрацию объектов-представителей других классов, “заинтересованных” в получении уведомления о событии,

  • отмену регистрации объектов, получающих уведомление о событии,

  • управление списком зарегистрированных объектов и процедурой уведомления о событии.

Реализация механизма управления по событиям предполагает два этапа:

  • объявление делегата,

  • объявление события.

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

Первый пример…

using System;

namespace Events01

{

// Делегат.

delegate int ClassDLG (int key);

// Классы, содержащие методы - обработчики событий.

class C1

{//===============================================================

public int C1f (int key)

{//_______________________________________________________________

Console.WriteLine("C1.C0f");

return key*2;

}//_______________________________________________________________

}//===============================================================

class C2

{//===============================================================

public int C2f (int key)

{//_______________________________________________________________

Console.WriteLine("C2.C0f");

return key*2;

}//_______________________________________________________________

}//===============================================================

// Стартовый класс.

class C0

{//===============================================================

static event ClassDLG ev0;

static event ClassDLG ev1;

public static int C0F (int key)

{//_______________________________________________________________

Console.WriteLine("C0.C0F");

return key*2;

}//_______________________________________________________________

public int C0f (int key)

{//_______________________________________________________________

Console.WriteLine("C0.C0f");

return key*2;

}//_______________________________________________________________

static void Main(string[] args)

{//_______________________________________________________________

int i;

Random rnd = new Random();

// Создаётся объект-представитель класса C1.

C1 obj1 = new C1();

// Подписная компания. Подписываются ВСЕ!

// В событии ev0 заинтересован:

// класс C0 статическим методом C0F.

ev0 += new ClassDLG(C0.C0F);

// В событии ev1 заинтересован:

// класс C0 методом C0f, вызываемым от имени безымянного объекта,

// класс C1 методом C1f, вызываемым от имени объекта obj1,

// класс C2 методом C2f, вызываемым от имени безымянного объекта.

ev1 += new ClassDLG((new C0()).C0f);

ev1 += new ClassDLG(obj1.C1f);

ev1 += new ClassDLG((new C2()).C2f);

// И вот какие события...

// Орёл или Решка!

for (i = 0; i < 100; i++)

{

Console.WriteLine("==={0}===",i);

switch (rnd.Next(0,2))

{

case 0: // Уведомляются ВСЕ заинтересованные в событии "выпадение 0".

ev0(i);

break;

case 1: // Уведомляются ВСЕ заинтересованные в событии "выпадение 0".

ev1(i);

break;

}

}

}//_______________________________________________________________

}//===============================================================

}

Второй пример…

using System;

namespace EVENTS

{

// Объявленние классов-делегатов.

// Класс-делегат со стандартными сигнатурой и спецификатором возвращаемого значения.

delegate int ClassDlg_1(int key, string str);

// Сигнатура делегата и возвращаемое значение могут быть любыми!

delegate int ClassDlg_2(int key);

// Тип второго параметра делегата для этого класса-делегата объявлен ниже.

delegate void ClassDlg_TimeInfo(object sourseKey, TimeInfoEventArgs eventKey);

//===================================================================

class TimeInfoEventArgs: EventArgs

{//==================================================================

public TimeInfoEventArgs(int hh, int mm, int ss)

{

hour = hh;

minute = mm;

second = ss;

}

public readonly int hour;

public readonly int minute;

public readonly int second;

}//==================================================================

//===================================================================

// Объявляются два класса

//===================================================================

class Doll_1

{

public ClassDlg_1 dlg1Doll_1; // Объявлен делегат “стандартного” вида.

public ClassDlg_2 dlg2Doll_1; // Объявлен делегат.

public ClassDlg_TimeInfo dlgTimeInfo; // Нужна ссылка на объект - параметр делегата.

// Объявлено соответствующее событие.

// Событие объявляется на основе класса делегата.

// Нет класса делегата – нет и события!

public event ClassDlg_2 eventDoll_1;

// Конструктор. В конструкторе производится настройка делегатов.

public Doll_1()

{

dlg1Doll_1 = new ClassDlg_1(F2Doll_1);

dlgTimeInfo = new ClassDlg_TimeInfo(TimeInfoDoll_1);

}

// Функции – члены класса, которые должны вызываться

// в ответ на уведомление о событии, на которое предположительно

// должен подписаться объект – представитель данного класса.

//=====================================================================

public int F0Doll_1(int key)

{

// Эта функция только сообщает...

Console.WriteLine(“this is F0Doll_1({0})”, key);

return 0;

}

public void F1Doll_1(int key)

{

// Эта функция ещё и УВЕДОМЛЯЕТ подписавшийся у неё объект...

// Что это за объект функция не знает!

Console.WriteLine(“this is F1Doll_1({0}), fire eventDoll_1!”, key);

if (eventDoll_1 != null) eventDoll_1(key);

}

public int F2Doll_1(int key, string str)

{

// Эта функция сообщает и возвращает значение...

Console.WriteLine(“this is F2Doll_1({0},{1})”, key, str);

return key;

}

void TimeInfoDoll_1(object sourseKey,TimeInfoEventArgs eventKey)

{

// А эта функция вникает в самую суть события, которое несёт

// Информацию и времени возбуждения события.

Console.Write(“event from {0}:”, ((SC)sourseKey).ToString());

Console.WriteLine(“the time is {0}:{1}:{2}”,eventKey.hour.ToString(),

eventKey.minute.ToString(),

eventKey.second.ToString());

}

}

//===================================================================

//===================================================================

// Устройство второго класса проще. Нет обработчика события “времени”.

class Doll_2

{

public ClassDlg_1 dlg1Doll_2;

public ClassDlg_2 dlg2Doll_2;

public event ClassDlg_2 eventDoll_2;

// В конструкторе производится настройка делегатов.

public Doll_2()

{

dlg1Doll_2 = new ClassDlg_1(F1Doll_2);

dlg2Doll_2 = new ClassDlg_2(F0Doll_2);

}

public int F0Doll_2(int key)

{

// Эта функция только сообщает...

Console.WriteLine(“this is F0Doll_2({0})”, key);

return 0;

}

public int F1Doll_2(int key, string str)

{

// Эта функция сообщает и возвращает значение...

Console.WriteLine(“this is F1Doll_2({0},{1})”, key, str);

return key;

}

public void F2Doll_2(int key)

{

// Эта функция ещё и УВЕДОМЛЯЕТ подписавшийся у неё объект...

Console.WriteLine(“this is F2Doll_2({0}), fire eventDoll_2!”, key);

if (eventDoll_2 != null) eventDoll_2(key);

}

}

//===================================================================

//===================================================================

class SC // Start Class

{

// Объявлен класс-делегат…

public static ClassDlg_2 dlgSC;

// В стартовом класса объявлены два события.

public static event ClassDlg_1 eventSC;

public static event ClassDlg_TimeInfo timeInfoEvent;

static public int FunSC(int key)

{

Console.WriteLine(“this is FunSC({0}) from SC”,key);

// Первое уведомление. В теле этой функции осуществляется передача

// управления методу ОБЪЕКТА, который заинтересован в данном событии.

// В данном случае событием в буквальном смысле является факт передачи

// управления функции FunSC. Какие одбъекты заинтересованы в этом

// событии – сейчас сказать невозможно. Здесь только уведомляют о

// событии. Подписывают заинтересованных – в другом месте!

eventSC(2*key, “Hello from SC.FunSC !!!”);

DateTime dt = System.DateTime.Now;

// Второе уведомление.

timeInfoEvent(new SC(), new TimeInfoEventArgs(dt.Hour,dt.Minute,dt.Second));

return key;

}

static void Main(string[] args)

{

// Объявили и определили два объекта.

// Так вот кто интересуется событиями!

Doll_1 objDoll_1 = new Doll_1();

Doll_2 objDoll_2 = new Doll_2();

// Подписали их на события.

// В событии eventSC заинтересованы объекты

// objDoll_1 и objDoll_2, которые здесь подписываются на

// события при помощи делегатов, которые были настроены

// на соответствующие функции в момент создания объекта.

// Конструкторы обоих классов только и сделали, что настроили

// собственные делегаты.

eventSC += objDoll_1.dlg1Doll_1;

eventSC += objDoll_2.dlg1Doll_2;

// А в событии timeInfoEvent заинтересован лишь

// объект–представитель класса Doll_1.

timeInfoEvent += objDoll_1.dlgTimeInfo;

// Определили делегата для функции SC.FunSC.

// Это собственная статическая функция класса SC.

dlgSC = new ClassDlg_2(SC.FunSC);

// А теперь достраиваем делегаты, которые

// не были созданы и настроены в конструкторах

// соответствующих классов.

objDoll_1.dlg2Doll_1 = new ClassDlg_2(objDoll_2.F0Doll_2);

objDoll_2.dlg1Doll_2 = new ClassDlg_1(objDoll_1.F2Doll_1);

// Подписали объекты на события.

objDoll_1.eventDoll_1 +=new ClassDlg_2(objDoll_2.F0Doll_2);

objDoll_2.eventDoll_2 +=new ClassDlg_2(objDoll_1.F0Doll_1);

// SC будет сообщать о времени!

// И не важно, откуда последует вызов функции.

// Событие в классе objDoll_1 используется для вызова

// статического метода класса SC.

objDoll_1.eventDoll_1 +=new ClassDlg_2(SC.dlgSC);

// Событие в классе objDoll_2 используется для вызова

// статического метода класса SC.

objDoll_2.eventDoll_2 +=new ClassDlg_2(SC.dlgSC);

// Работа с делегатами.

objDoll_1.dlg2Doll_1(125);

objDoll_2.dlg1Doll_2(521, “Start from objDoll_2.dlg1Doll_2”);

// Работа с событиями. Уведомляем заинтересованные классы и объекты!

// Что-то не видно особой разницы с вызовами через делегатов.

objDoll_1.F1Doll_1(125);

objDoll_2.F2Doll_2(521);

// Отключили часть приемников.

// То есть отказались от получения некоторых событий.

// И действительно. Нечего заботиться о чужом классе.

objDoll_1.eventDoll_1 -= new ClassDlg_2(SC.dlgSC);

objDoll_2.eventDoll_2 -= new ClassDlg_2(SC.dlgSC);

// Опять работа с событиями.

objDoll_1.F1Doll_1(15);

objDoll_2.F2Doll_2(51);

}

}

}