Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
тюмгу / Лекции КБ ИБАС 1 курс 2 семестр / лекция18 Безопасность 2018.ppt
Скачиваний:
15
Добавлен:
08.12.2019
Размер:
653.82 Кб
Скачать

Делегаты

Делегат — это вид класса, предназначенный для хранения ссылок на методы. Т.е., делегат представляет метод (методы).

Экземпляр делегата (как и любого другого класса) можно передать в качестве параметра, а затем вызвать инкапсулированный в нем метод.

Делегаты используются для поддержки событий, а также как самостоятельная конструкция языка.

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

[ атрибуты ] [ спецификаторы ] delegate тип имя([ параметры ])

Пример описания делегата:

public delegate void D ( int i );

Базовым классом делегата является класс System.Delegate

Передача делегатов в методы

Поскольку делегат является классом, переменную типа делегата можно передавать в методы в качестве параметра.

Таким образом обеспечивается функциональная параметризация: в метод можно передавать не только различные данные, но и различные функции их обработки. Функциональная параметризация применяется для создания универсальных методов

и обеспечения возможности обратного вызова.

Вкачестве простейшего примера универсального метода можно привести метод вывода таблицы

значений функции, в который передается диапазон значений аргумента, шаг его изменения и вид вычисляемой функции.

Пример: решение алгебраических уравнений методом бисекции

delegate double FUNC(double x); // представляет функцию y=F(x)

static double RootBis(FUNC f, double a, double b, double eps)

{

if (f(a) * f(b) > 0) return double.NaN; while (Math.Abs(b - a) >= eps)

{

double c = (a + b) / 2;

if (f(a) * f(c) > 0) a = c; else b = c;

}

return (a + b) / 2;

static double F1(double x)

{

return x * x - Math.Cos(x);

}

static double F2(double x)

{

return Math.Exp(x) - 1 / x;

}

static void Main()

{

FUNC myF = new FUNC(F1); Console.WriteLine(RootBis(myF, 0, 5, 1e-6)); myF = F2;

Console.WriteLine(RootBis(myF, 0, 5, 1e-6));

Console.WriteLine(RootBis(F1, 0, 5, 1e-6));

Console.ReadLine();

}

public delegate double Fun(double x); // объявление делегата class Test

{

public static void Table(string F_Name, Fun F, double x, double x_fin, double dx)

{

Console.WriteLine("\n Таблица функции " + F_Name); while (x <= x_fin)

{

Console.WriteLine("| {0,5:f1} | x += dx;

}

Console.WriteLine(" ---------------------

}

public static double Simple(double x) { static void Main()

{

Table("Sin", new Fun(Math.Sin), -2, 2, Table("Simple", new Fun(Simple), 0, 3,

}

}

Возможны и другие способы вызова:

{

Table("1", Simple, 0, 3, 1);

Table("2", Math.Sin, -2, 2, 0.5); // new Fun(Math.Sin)

Table("3", delegate(double 1);

}

Делегат может представлять несколько методов:

public delegate void Del(); // объявление делегата

class Program

{

public static void A() { Console.Write('A'); } public static void P() { Console.Write('P'); } static void Main(string[] args)

{

Del a = A, p = P, d = null; d += A; d += P; d += P; d();

Console.WriteLine(); d = p + a + p + a; d();

Console.ReadLine();

}

}

//вызов одного виртуального делегата (пула) приводит к вызову

//нескольких «привязанных» к нему методов

Реализация паттерна

«наблюдатель»

Рассмотрим применение делегатов для обеспечения связи между объектами по типу «источник —

наблюдатель».

Врезультате разбиения системы на множество совместно работающих классов появляется необходимость поддерживать согласованное состояние взаимосвязанных объектов. При этом для упрощения модификации кода желательно избежать жесткой связанности классов.

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

Программисты часто используют одну и ту же схему организации и взаимодействия объектов в разных контекстах. За такими схемами закрепилось название

паттерны, или шаблоны проектирования. Описанная стратегия известна под названием паттерн «наблюдатель».

Наблюдатель (observer) определяет между объектами зависимость типа «один ко многим», т.е., при изменении состоянии одного объекта все зависящие от него объекты получают извещение

и автоматически обновляются.

Впримере котором демонстрируется схема оповещения источником трех наблюдателей (двух

классов). Гипотетическое изменение состояния объекта моделируется сообщением «Ух-ты!».

Описание класса - источника:

public

delegate void Del(object o); // объявление делегата

class Subj

// класс-источник

{

 

 

 

Del

dels;

// объявление экземпляра делегата

(пула)

 

 

// пока делегат (пул) пустой (==null)

int

CountD = 0;

// число делегатов в пуле

public void Register(Del d)

{

 

// регистрация делегата d в пуле dels

 

dels += d;

// добавление делегата в конец пула

 

CountD++;

 

}

public void OPPA() // метод оповещения

{

Console.WriteLine(" ----------

Ух-ты!");

if (dels != null) dels(this);

 

//запуск пула - оповещение наблюдателей,

//передаётся ссылка на источник (this)

}

public override string ToString()

{ return " источник с "+CountD+ " делегатами "; }

}