Події. Приклади використання анонімного методу та лямбда-виразу в якості події. Обробники подій, що використовуються в середовищі .NET

Події. Приклади використання анонімного методу та лямбда-виразу в якості події. Обробники подій, що використовуються в середовищі .NET


Зміст


1. Приклад використання анонімного методу в якості обробника події

У прикладі продемонстровано використання анонімного методу в якості обробника події для додатку, створеного за шаблоном Windows Forms Application. В анонімному методі обчислюється площа круга на основі заданого радіусу r.
Послідовність кроків наступна.
Нехай тип делегату та подія оголошені в деякому класі наступним чином:

// оголосити тип делегату CalcFigure
delegate double CalcFigure(double r);

// оголосити подію CF
event CalcFigure CF;

Тоді, програмний код, що демонструє подію буде мати вигляд:

// використання анонімного методу в якості обробника події
CF += delegate(double r)
{
    // у методі обчислюється площа круга радіусу r
    const double Pi = 3.1415;
    double res;
    res = Pi * r * r;
    return res;
};

// перевірка
double R = 3.0;
double Res;
Res = CF(R); // Res = 28.2735

Якщо додаток створено за шаблоном Windows Forms Application, то усі ці дії можна виконати, наприклад, в обробнику події кліку на кнопці. У цьому випадку, програмний код модуля форми буде мати приблизно такий вигляд:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainEvents03
{

    public partial class Form1 : Form
    {
        // оголосити тип делегату CalcFigure
        delegate double CalcFigure(double r);

        // оголосити подію CF
        event CalcFigure CF;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // використання анонімного методу в якості обробника події
            CF += delegate(double r)
            {
                // у методі обчислюється площа круга радіусу r
                const double Pi = 3.1415;
                double res;
                res = Pi * r * r;
                return res;
            };

            // перевірка
            double R = 3.0;
            double Res;
            Res = CF(R); // Res = 28.2735
            label1.Text = Res.ToString();
        }
    }
}

 

2. Приклад використання лямбда-виразу в якості обробника події

У коді нижче демонструється використання лямбда-виразу в якості обробника події. Так само, як і в попередньому прикладі обчислюється площа круга.
Кроки демонстрації лямбда-виразу такі самі як і в попередньому прикладі.
Спочатку в класі потрібно оголосити тип делегату та подію:

// оголосити тип делегату CalcFigure
delegate double CalcFigure(double r);

// оголосити подію CF
event CalcFigure CF;

Потім в деякому методі цього класу можна сформувати наступний код, що демонструє використання лямбда-виразу

// використання лямбда-виразу в якості обробника події
CF = (r) =>
{
    // обчислюється площа круга радіусу r
    double res;
    res = 3.1415 * r * r;
    return res;
};

// перевірка
double RR, Res;
RR = 2.0;
Res = CF(RR);

 

3. Які вимоги пред’являються до обробників подій для забезпечення сумісності з середовищем .NET?

Для того, щоб власні обробники подій були сумісні з середовищем .NET вони потрібні мати два параметри:

  • перший параметр – посилання на об’єкт, що формує подію;
  • другий параметр – параметр типу EventArgs.

 

4. Яка загальна форма обробника події, що є сумісним з .NET середовищем?

Загальна форма .NET-сумісного обробника події:

void імя_обробника(object відправник, EventArgs e)
{
    // ...
}

де

  • імя_обробника – ім’я методу обробника події, що є сумісним з .NET середовищем;
  • EventArgs – клас, що містить додаткову інформацію про подію.

У цьому випадку тип делегату, при оголошенні, має мати таку саму сигнатуру.



 

5. Приклад, що демонструє використання події, що є сумісною з середовищем .NET

Спочатку потрібно оголосити тип делегату, сигнатура якого є сумісною з .NET середовищем. Наприклад, це може виглядати так:

// Оголосити тип делегату
delegate void MyTypeDelegate(object sndr, EventArgs e);

Наступний крок – оголошення події:

// Оголосити подію
event MyTypeDelegate EMD;

Оголошення методів, що сумісні з подією може бути таким:

// Оголошення методів - обробників події
void EventHandler1(object sndr, EventArgs e)
{
    // команди, інструкції
    // ...
}

void EventHandler2(object sndr, EventArgs e)
{
    // команди, інструкції
    // ...
}

void EventHandler3(object sndr, EventArgs e)
{
    // команди, інструкції
    // ...
}

Демонстрація використання події з деякого методу, наприклад, обробника події кліку на кнопці button1_Click():

private void button1_Click(object sender, EventArgs e)
{
    // Демонстрація роботи події, що сумісна з середовищем .NET Framework

    // Сформувати список методів, що викликаються при запуску події
    EMD = EventHandler1;
    EMD += EventHandler3;
    EMD += EventHandler2;

    // Запуск події
    EMD(this, e);

    // Інший варіант запуску для події button1_Click
    EMD(sender, e);
}

Увесь код модуля Form1.cs, що демонструє даний приклад має вигляд:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainEvents05
{
    public partial class Form1 : Form
    {
        // Оголосити тип делегату
        delegate void MyTypeDelegate(object sndr, EventArgs e);

        // Оголосити подію
        event MyTypeDelegate EMD;

        public Form1()
        {
            InitializeComponent();
            label1.Text = "";
        }

        // Оголошення методів - обробників події
        void EventHandler1(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler1 ";
        }

        void EventHandler2(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler2 ";
        }

        void EventHandler3(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler3 ";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Демонстрація роботи події, що сумісна з середовищем .NET Framework

            // Сформувати список метод, що викликаються при запуску події
            EMD = EventHandler1;
            EMD += EventHandler3;
            EMD += EventHandler2;

            // Запуск події
            EMD(this, e);

            // Інший варіант запуску для події button1_Click
            EMD(sender, e);
        }
    }
}

 

6. Яке призначення узагальненого делегату EventHandler<TEventArgs>

Узагальнений делегат EventHandler<TEventArgs> є реалізований в середовищі .NET. Цей делегат призначений для заміни власного делегату події.

Наприклад, в п.5 подія

event MyTypeDelegate EMD;

може бути замінена на такий код

event EventHandler<EventArgs> EMD;

а тип делегату оголошувати не потрібно.

 

7. Приклад коду, що використовує узагальнений делегат EventHandler, який реалізований в середовищі .NET

У даному прикладі виконується такий самий код, як і в п. 5. Тільки замість власного типу делегату використовується узагальнений делегат EventHandler, з допомогою якого оголошується подія.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TrainEvents05
{
    public partial class Form1 : Form
    {
        // Оголошувати власний тип делегату не потрібно

        // Оголосити подію з допомогою узагальненого делегату EventHandler
        event EventHandler<EventArgs> EMD;

        public Form1()
        {
            InitializeComponent();
            label1.Text = "";
        }

        // Оголошення методів - обробників події
        void EventHandler1(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler1 ";
        }

        void EventHandler2(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler2 ";
        }

        void EventHandler3(object sndr, EventArgs e)
        {
            label1.Text += "EventHandler3 ";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Демонстрація роботи події, що сумісна з середовищем .NET Framework

            // Сформувати список методів, що викликаються при запуску події
            EMD = EventHandler1;
            EMD += EventHandler3;
            EMD += EventHandler2;

            // Запуск події
            EMD(this, e);

            // Інший варіант запуску для події button1_Click
            EMD(sender, e);
        }
    }
}

У вищенаведеному коді рядок

event EventHandler<EventArgs> EMD;

можна замінити спрощеним рядком

event EventHandler EMD;

 

8. Яке призначення об’єкту-заповнювача Empty з класу EventArgs

В середовищі .NET, в деяких випадках роботи з подіями, параметр EventArgs є непотрібним. У цих випадках доцільним є використання об’єкту-заповнювача Empty з класу EventArgs. Це здійснюється з метою спрощення створення коду.

Так, у попередньому прикладі рядки запуску події

// Запуск події
EMD(this, e);

// Інший варіант запуску для події button1_Click
EMD(sender, e);

можна замінити рядками

// Запуск події
EMD(this, EventArgs.Empty);

// Інший варіант запуску для події button1_Click
EMD(sender, EventArgs.Empty);

 


Зв’язані теми