Шаг 187.
Язык программирования C#. Начала.
Делегаты и события. Примеры использования
На этом шаге мы рассмотрим несколько примеров решения задач, в которых используются делегаты, лямбда-функции и события.
Здесь мы рассмотрим несколько программ, в которых используются ранее рассмотренные делегаты, лямбда-функции и события.
Задание 1.
Напишите программу, в которой с помощью делегатов и анонимных методов (лямбда-выражений) создается экземпляр делегата, который вызывается без аргументов, а результатом возвращает
текстовое значение с названием дня недели ("Понедельник", "Вторник" и так до "Воскресенья"). При каждом новом вызове экземпляра результатом возвращается название следующего дня недели.
После "Воскресенья" результатом возвращается "Понедельник" и так далее.
Раскрыть/скрыть решение и комментарии.
Текст программы достаточно простой:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace pr187_1
{
delegate string Alpha();
class Program
{
static void Main()
{
// Создание экземпляра делегата:
Alpha show;
// Номер дня недели
int nom = -1;
// Анонимный метод:
show = delegate()
{
// Перечень дней недели:
string[] Days = new string[] { "Понедельник", "Вторник", "Среда",
"Четверг", "Пятница", "Суббота", "Воскресенье" };
return Days[++nom % 7];
};
// Вывод названия дня недели:
for (int i = 1; i < 12; i++)
{
Console.WriteLine("{0}-й день: {1}", i, show());
}
// Задержка:
Console.ReadLine();
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения приведен на рисунке 1.
Рис.1. Результат работы приложения
Немного прокомментируем приведенный текст.
Сначала описываем делегат Alpha, не принимающий параметров и возвращающий строку. Мы будем использовать его для получения очередного дня недели.
Затем описываем и создаем анонимный делегат show, который будет возвращать очередной день недели из массива Days. Для этого используем целочисленную переменную nom,
остаток от деления которой на количество дней (7), будет определять номер очередного дня недели.
В цикле вызываем делегат, который возвращает название очередного дня недели.
Задание 2.
Напишите программу, содержащую статический метод с тремя действительными (тип
double) аргументами. Результатом статического метода является ссылка на метод, вычисляющий квадратичный
трехчлен с коэффициентами, определяемыми аргументами статического метода. Другими словами, если статический метод вызывается с числовыми аргументами
a,
b и
с, то
результатом является ссылка на метод, который для аргумента
x типа
double результатом вычисляет значение выражения
a*x*x+b*x+c.
Раскрыть/скрыть решение и комментарии.
Достаточно интересная задача, над решеним которой пришлось подумать. Вот текст программы:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace pr187_2
{
// Объявление делегата с
// аргументом x:
delegate double MyDelegate(double x);
class Program
{
// Статический метод, вычисляющий
// значение квадратного трехчлена:
static MyDelegate apply(double a, double b, double c)
{
// Лямбда-выражение, определяющее
// правило вычисления значения:
return x => a * x * x + b * x + c;
}
static void Main()
{
// Значение x:
double x = 2;
// Значения коэффициентов:
double a = 1, b = 2, c = 3;
// Результат:
double d = apply(a, b, c)(x);
// Вывод результата:
Console.WriteLine("apply({0}, {1}, {2})({3}) = {4}", a, b, c, x, d);
// Задержка:
Console.ReadLine();
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения изображен на рисунке 2.
Рис.2. Результат работы приложения
Надеемся, что комментариев, приведенных в программе будет достаточно для понимания ее работы. Отметим только, что при описании делегата MyDelegate указывается аргумент - переменная
x, для которой вычисляется значение квадратного трехчлена. Статический метод apply() показывает, как вычислить результат, когда переменная x получит конкретное значение.
Задание 3.
Напишите программу, в которой есть класс с событием. Событие обрабатывается методами, имеющими текстовый аргумент и не возвращающими результат. У класса должно быть текстовое поле, в
которое при создании объекта класса записывается название объекта. В классе должен быть описан метод для генерирования события, который вызывается без аргументов. При генерировании
события аргументом передается значение текстового поля объекта, генерирующего событие. Еще один класс, описанный в программе, должен содержать метод с текстовым аргументом, не
возвращающий результат. При вызове метод отображает значение своего текстового аргумента. В главном методе программы необходимо создать два объекта первого класса и один объект второго
класса. Для событий объектов первого класса обработчиком регистрируется метод объекта второго класса (получается, что метод одного и того же объекта зарегистрирован обработчиком для событий
двух объектов). Для каждого из объектов первого класса необходимо сгенерировать событие. При этом метод, зарегистрированный обработчиком, должен выводить название объекта, сгенерировавшего событие.
Раскрыть/скрыть решение и комментарии.
По нашему мнению, хоть текст задания большой, но само задание несложное. За основу реализации мы взяли программу из 184 шага. Ее полный текст приведен ниже.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace pr187_3
{
// Объявление делегата:
delegate void MyDelegate(string txt);
// Класс с событием:
class MyClass
{
private string name;
// Конструктор
public MyClass(string ni)
{
name = ni;
}
// Объявление события:
public event MyDelegate MyEvent;
// Метод для генерирования события:
public void RaiseMyEvent()
{
// Если для события предусмотрены обработчики:
if (MyEvent != null)
{
// Генерирование события:
MyEvent(name);
}
}
}
// Класс:
class Alpha
{
// Текстовое поле:
private string text;
// Конструктор:
public Alpha(string txt)
{
text = txt;
}
// Метод отображает сообщение:
public void show(string obj)
{
Console.WriteLine("Объект, сгенерировавший событие: " + obj);
Console.WriteLine("Сообщение: " + text);
}
}
// Класс с главным методом:
class Program
{
// Главный метод:
static void Main()
{
// Два объекта первого класса:
MyClass A = new MyClass("A");
MyClass B = new MyClass("B");
// Один объект второго класса:
Alpha Obj = new Alpha("obj");
// Добавление обработчика для события:
A.MyEvent += Obj.show;
B.MyEvent += Obj.show;
// Генерация события:
A.RaiseMyEvent();
Console.WriteLine();
// Генерация события:
B.RaiseMyEvent();
Console.WriteLine();
// Задержка:
Console.ReadLine();
}
}
}
Архив проекта можно взять
здесь.
Результат работы приложения изображен на рисунке 3.
Рис.3. Результат работы приложения
Надеемся, что понимание ее работы не вызовет затруднений.
Со следующего шага мы начнем знакомиться со перечислениями и структурами.
Предыдущий шаг
Содержание
Следующий шаг