Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
инфа теория передел.docx
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
447.59 Кб
Скачать

22 Делегаты

Для реализации обратных вызовов в C# используется новая разновидность пользовательских типов - delegate (делегат). C помощью данного типа описываются типы данных, которые могут хранить ссылки на методы с заданной сигнатурой. C использование ключевого слова delegate можно описать новый тип.

    • Новый тип можно описать с помощью класса:

class xxxx

{...}

    • И новый тип можно описать с помощью делегата:

delegate <сигнатура>

Тип delegate поддерживает три важных элемента информации:

    • Адрес метода на который он ссылается.

    • Параметры (если они есть) данного метода.

    • Возвращаемое методом значение.

Пример работы с делегатом

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

public delegate int MyFunc(int n);

// объявление о переменной – ссылке на метод

MyFunc rf = new MyFunc (Calc); // или rf = Calc;

// вызов метода с помощью ссылки

int k = f(5);

. . .

public static int Calc (int n) { … }

Стандартные делегаты

  • В библиотеке FCL описаны стандартные обобщенные делегаты, которые активно используются в методах классов библиотеки:

  • System.Action() – принимает значение (или значения) и ничего не возвращает;

public delegate void Action<T>( T obj )

  • System.Comparison() – принимает два параметра и возвращает целое значение (< 0: x < y; 0: x == y; > 0: x > y)

public delegate int Comparison<T>( T x, T y )

  • System.Converter() – преобразование объекта из одного типа в другой

public delegate TOutput Converter<TInput, Toutput> ( TInput input )

  • System.EventHandler – обработчик событий

public delegate void EventHandler<TEventArgs>

( Object sender, TEventArgs e ) where TEventArgs : EventArgs

  • System.Func() – принимает значение (или значения) и возвращает результат

public delegate TResult Func<T, TResult>( T arg )

  • System.Predicate() – принимает значение и возвращает bool

public delegate bool Predicate<T>( T obj )

Лямбда выражения это анонимные методы (функции), которые могут содержать выражения и операторы и могут использоваться для создания делегатов или деревьев выражений (expression tree types).Все lambda выражения используют лямбда операция =>, который читается как "перейти к".

  • Например, лямбда выражение x => x * x читается, как "x переходит к x умноженному на x."

  • Данное лямбда выражение может быть присвоено типу delegate следующим образом:

delegate int del(int i);

static void Main(string[] args)

{

del myDelegate = x => x * x;

int j = myDelegate(5); //j = 25

}

  • Способ записи

(int x) => x + 1 ; // is the same as

(int x) => { return x + 1; }

23 События

  • С помощью делегатов в классах можно описывать события.

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

Объекты одного класса могут использовать объекты других классов. Для этого они создают объекты требуемого класса и вызывают его методы (передают ему сообщения). При работе вызванных методов часто возникает необходимость передать сообщения о возникших ситуациях (важных изменения в своей работе) объектам вызывающего класса, без завершения их работы. Для передачи таких сообщений и используются специальные элементы класса – события.

Программирование основанное на событиях – event driven programming.

  • Вначале объявляется делегат, как это рассматривалось ранее. Объявление делегата описывается в некотором классе. Но, часто, это объявление находится вне класса в пространстве имен.

public delegate <тип> <имя_делегата> ([параметры]);

    • Например:

public delegate void MyHandler (object o, int n);

  • Объявить событие как экземпляр соответствующего делегата. При этом используется ключевое слово event (это гарантирует, что экземпляр события не может быть вызван в других классах).

рublic event <имя_делегата> <имя_события>;

    • Например:

public event MyHandler MyEvent;

  • Для инициирования события требуется просто вызвать на выполнение экземпляр делегата.

    • Например:

  • if (MyEvent != null) // проверка, что для события заданы обработчики

  • MyEvent(this, i); // если есть обработчики, то запускаем событие

  • Пример описания события

  • // Объявление нового типа – делегата

  • public delegate void MyHandler (object o, int n);

  • // объявление класса с событием

  • public class ClassWithEvent { // класс с событием

  • // Создание экземпляра делегата - событие

  • public event MyHandler MyEvent;

  • // поле класса

  • private int Volume = 0;

  • // конструктор класса – парамер – объем работы

  • public EventClass(int p){if (p > 0) Volume = p;}

//описание метода выполняющего долгую работу (в данном примере бессмысленную)

public void LongWork(){

double s = 0; int k = 0;

int st = Volume / 10; // десятая часть работы

for (int i = 0; i < Volume; i++) {

s += Math.Atan(Math.Sqrt(i) * Math.Sqrt(i));

if (k == st) {// выполнена заданная часть работы

if (MyEvent != null){

int n = (int)(i*100.0)/Volume;

MyEvent(this, n); // запускаем событие

}

k = 0;

}

else k += 1;

} } }