Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c#_theoretical_2.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
750.08 Кб
Скачать

Події: створення та обробка

Подія − це елемент класу, який дозволяє об’єктам цього класу відправляти повідомлення іншим об’єктам про зміну свого стану. При цьому для об’єктів, які є спостерігачами події, активізуються методи-реакції (методи-обробники чи то просто обробники) цієї події. Методи-реакції мають бути зареєстровані у об’єкті-джерелі події. Отже, механізм подій є нічим іншим як способом формалізації шаблону «спостерігач», який ми розглядали у попередній темі.

Розглянемо використання механізму подій на прикладі спрощеного варіанту об’єктно-орієнтованої програми дослідження функцій у відповідності до наступної діаграми:

Мал. 1. Діаграма об’єктів задачі дослідження функції.

Спочатку наведемо приклад реалізацій класів об’єктів нашої задачі.

// клас обєкта «Головне меню»

class MainMenu

{

// пункти головного меню

string[] items;

// номер обраного пункту головного меню

char SelectedItem;

// конструктор без параметрів

public MainMenu()

{

items = new string[4];

items[0] = "Sin(x)";

items[1] = "Cos(x)";

items[2] = "Exp(x)";

items[3] = "Вихiд";

}

// метод виводу головного меню на консоль

public void Show()

{

Console.Clear();

Console.WriteLine("Програма дослiдження функцiй");

for (int i = 0; i < items.Length; i++)

Console.WriteLine("{0} - {1}",i+1, items[i]);

Console.Write("Ваш вибiр ");

SelectedItem = Console.ReadKey().KeyChar;

if (SelectedItem == '4') return;

}

}

// клас обєкта «Функція»

class Function

{

delegate double ElementaryFunction(double x);

// ототожнюється з номером функції

public ElementaryFunction f;

}

// клас обєкта «Табулятор»

class Tabulator

{

// лівий кінець відрізку, на якому проводиться табулювання функції

double a;

// правий кінець відрізку, на якому проводиться табулювання функції

double b;

// крок табулювання

double step;

// точка із відрізку [a,b]

double X;

// значення функції у точці Х

double Y;

// метод побудови таблиці значень функції

void BuildTable()

{

X = a;

Console.WriteLine(" ----- X ----- Y ----- ");

while(X<=b)

{

Console.WriteLine("| {0,8:0.000} | {1,8:0.000} |", X, Y);

X+=step;

}

}

}

Перейдемо тепер до питання реалізації механізму подій у класах об’єктів задачі. У загальному випадку механізм подій передбачає створення події та обробку події.

1. Створення події передбачає наступні кроки.

1.1. Опис делегата, який задає сигнатуру методів-обробників події. У мові C# при описі делегата, який задає сигнатуру методів-обробників подій, загальноприйнятним є дотримання наступних правил:

  • ім’я делегата закінчується суфіксом EventHandler;

  • делегат отримує два параметри:

    • перший параметр задає джерело (відправника) події та має тип object;

    • другий параметр задає аргументи події − додаткові параметри, які надають обробникам події специфічну інформацію про цю подію. Якщо є необхідність у аргументах події, то для цього створюють похідний клас (ім’я якого закінчується суфіксом EventArgs) від стандартного класу System.EventArgs, в який додають необхідну інформацію.

    • Якщо обробникам події не потрібні аргументи події, то при оголошенні відповідної події використовують стандартний делегат System.EventHandler:

[SerializableAttribute] [ComVisibleAttribute(true)]

public delegate void EventHandler(оbject sender, EventArgs e);

У нашій програмі є дві події: вибір конкретної функції у головному меню та отримано нове значення у табуляторі. Відповідно потрібно описати два делегати. Ці делегати опишемо у просторі імен MyEvents та програмно реалізуємо у окремому файлі MyEventHandler.cs. З урахуванням зазначених вище загальноприйнятих домовленостей маємо:

public delegate void ItemSelectEventHandler(object sender, ItemSelectEventArgs e);

public delegate void CalculateEventHandler(object sender, CalculateEventArgs e);

Відповідні класи аргументів цих подій опишемо у просторі імен MyEvents та програмно реалізуємо у окремому файлі MyEventArgs.cs:

public class ItemSelectEventArgs : System.EventArgs

{

char _SelectedItem;

public ItemSelectEventArgs(char item)

{

_SelectedItem = item;

}

public char SelectedItem

{

get { return _SelectedItem; }

}

}

public class NewXEventArgs : System.EventArgs

{

double x;

public double Y;

public NewXEventArgs(double arg)

{

x = arg;

}

public double X

{

get { return x; }

}

}

1.2. Опис події. Оголошення події здійснюється у класі відповідного об’єкта-джерела. У найпростішому варіанті загальний синтаксис опису події наступний:

[атрибути] [специфікатори] event тип імя_події;

При описі подій можуть бути застосованими специфікатори new, public, protected, internal, private, static, virtual, sealed, override, abstract та extern. Наприклад, так само як і методи подія може бути статичною, тоді вона стосується класу в цілому. Тип події − це тип делегата, на якому базується подія. Оголошення подій у класах відповідних об’єктів нашої задачі наступне:

class MainMenu

{

...

// оголошення події про вибір пункту головного меню, тобто про вибір конкретної функції

public event ItemSelectEventHandler ItemSelect;

}

class Tabulator

{

...

// оголошення події обчислення нового табличного значення

public event NewXEventHandler NewX;

}

1.3. Опис метода (методів), які породжують (ініціюють) подію. У класі об’єкта-джерела повинен бути визначений метод (методи), який би забезпечував настання події − у відповідний момент гарантував сповіщення всіх зареєстрованих спостерігачів про зміну стану об’єкта. Загальноприйнятим у мові C# є складати ім’я методу, що ініціює подію, із префікса On та імені події.

class MainMenu

{

...

// метод виводу головного меню на консоль

public void Show()

{

Console.Clear();

Console.WriteLine("Програма дослiдження функцiй");

for (int i = 0; i < items.Length; i++)

Console.WriteLine("{0} - {1}",i+1, items[i]);

Console.Write("Ваш вибiр ");

SelectedItem = Console.ReadKey().KeyChar;

if (SelectedItem == '4') return;

// ініціювання події вибору пункту головного меню

OnNewItemSelect(new ItemSelectEventArgs(SelectedItem));

}

...

// метод, який ініціює подію вибору нового пункту головного меню

public void OnNewItemSelect(ItemSelectEventArgs e)

{

if (ItemSelect != null) ItemSelect(this, e);

}

}

class Tabulator

{

...

void BuildTable()

{

X = a;

// ініціювання події про отримання нового значення X

OnNewX(new NewXEventArgs(X));

Console.WriteLine(" ----- X ----- Y ----- ");

while(X<=b)

{

Console.WriteLine("| {0,8:0.000} | {1,8:0.000} |", X, Y);

X+=step;

// ініціювання події про отримання нового значення X

OnNewX(new NewXEventArgs(X));

}

}

...

// метод, який ініціює подію отримання нового значення X

public void OnNewX(NewXEventArgs e)

{

if (NewX != null)

{

NewX(this, e);

Y = e.Y;

}

}

}

2. Обробка події здійснюється в класах об’єктів-спостерігачів (об’єктів-отримувачів повідомлення). Для цього у відповідних класах описуються методи-обробники події, сигнатура яких має відповідати типу делегата оголошеного у пункті 1.1. Для нашої визначимо методи-реакції наступним чином:

class Function

{

...

public void SelectFunction(object sender, ItemSelectEventArgs e)

{

if (sender is MainMenu)

{

switch (e.SelectedItem)

{

case '1': f = Math.Sin; break;

case '2': f = Math.Cos; break;

case '3': f = Math.Exp; break;

}

}

}

//реакція на обчислення нового значення X у табуляторі

public void Calculate(object sender, NewXEventArgs e)

{

if(sender is Tabulator) e.Y=f(e.X);

}

}

class Tabulator

{

...

// реакція на подію, коли вибрана функція

public void Activate(object sender, ItemSelectEventArgs e)

{

if (sender is MainMenu)

{

Console.Clear();

Console.Write("a= "); a = double.Parse(Console.ReadLine());

Console.Write("b= "); b = double.Parse(Console.ReadLine());

Console.Write("Введiть крок: "); step = double.Parse(Console.ReadLine());

BuildTable();

Console.ReadKey();

}

}

}

3. Реєстрація на подію. Кожен об’єкт, який хоче отримувати повідомлення, повинен зареєструвати в об’єкті-джерелі (відправнику) метод-обробник події, який був реалізований у пункті 2. Оскільки події підтримують операції += та -=, які додають метод-обробник у список та видаляють його зі списку, то вже не потрібно описувати метод реєстрації на подію.

class Program

{

static void Main(string[] args)

{

MainMenu MyMainMenu = new MainMenu();

Function MyF = new Function();

Tabulator MyTable = new Tabulator();

// реєстрація спостерігачів на події

MyMainMenu.ItemSelect += MyF.SelectFunction;

MyMainMenu.ItemSelect += MyTable.Activate;

MyTable.NewX += MyF.Calculate;

// програма починається із виводу головного меню на консоль

MyMainMenu.Show();

}

}

45

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]