События. Примеры использования анонимного метода и лямбда-выражения в качестве события. Обработчики событий, которые используются в среде .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);

 


Связанные темы