Разделы презентаций


Делегаты

Содержание

ДелегатыДелегат — это объект, который может ссылаться на метод - создавая делегат, мы создаем объект, который может содержать ссылку на метод и этот метод можно вызвать посредством соответствующей ссылки. Т. о.,

Слайды и текст этой презентации

Слайд 1Делегаты. События

Делегаты. События

Слайд 2Делегаты
Делегат — это объект, который может ссылаться на метод -

создавая делегат, мы создаем объект, который может содержать ссылку на

метод и этот метод можно вызвать посредством соответствующей ссылки. Т. о., делегат может вызывать метод, на который он ссылается.

Делегат – это так называемый “безопасный указатель на функцию”(делегаты C# = указатель на функцию в С)

Делегаты C# могут вызывать более одной функции (при совместном комбинировании двух делегатов результатом будет делегат, который вызывает их обоих).

Делегат - это класс отнаследованный от базового класса System.MulticastDelegate.

Делегат можно объявлять как в классе, так и просто в пространстве имен.
ДелегатыДелегат — это объект, который может ссылаться на метод - создавая делегат, мы создаем объект, который может

Слайд 3во время выполнения программы один и тот же делегат можно

использовать для вызова различных методов, просто заменив метод, на который

ссылается этот делегат (метод, который будет вызван делегатом, определяется не в период компиляции программы, а во время ее работы (достоинство делегата)).

delegate тип_возврата имя(список_параметров);

тип_возврата - собой тип значений, возвращаемых методами, которые этот делегат будет вызывать.
список_параметров - параметры, принимаемые методами, которые вызываются посредством делегата,

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

Делегат может вызывать либо метод экземпляра класса, связанный с объектом, или статический метод, связанный с классом.
во время выполнения программы один и тот же делегат можно использовать для вызова различных методов, просто заменив

Слайд 4Создание делегата
Объявляется сам делегат как тип и сразу же задается

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

Объявляется

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

Создаются сами объекты делегата, каждый из которых адресует одну функцию, и комбинируются в коллекцию, на которую указывает объявленная ссылка.

Коллекция - собой список адресуемых делегатом функций и поддерживается операциями += и -= или статическими методами  Delegate.Combine() и Delegate.Remove()

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

Создание делегатаОбъявляется сам делегат как тип и сразу же задается прототип функций, которые в будущем могут адресоваться

Слайд 5Одноадресная работа делегатов
Во время выполнения программы один и тот же

делегат можно использовать для вызова разных методов одинаковой сигнатуры простой

заменой метода, на который ссылается делегат (главное достоинство делегата, что адресуемый им метод определяется не на этапе компиляции, а в период выполнения). Заменяя в делегате адресуемые функции мы обеспечим их полиморфный вызов.

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

Одноадресная работа делегатовВо время выполнения программы один и тот же делегат можно использовать для вызова разных методов

Слайд 6class DelegateTest {

// Объявляем функции с сигнатурой делегатов

public void Show1() {
Console.WriteLine("Вызов: void Show1()"); }
// Объявляем функции с сигнатурой делегатов
public void Show2() {
Console.WriteLine("Вызов: void Show2()"); }
// Объявляем функции с сигнатурой делегатов
public int Draw1(string str1) {
Console.WriteLine("Вызов: {0}", str1); return 1; }
// Объявляем функции с сигнатурой делегатов
public int Draw2(string str2) {
Console.WriteLine("Вызов: {0}", str2); return 2; }
// Объявляем статическую функцию
public static int Print(string str) {
Console.WriteLine("Вызов: {0}", str); return 0; } }
// Объявляем делегат в пространстве имен
delegate void TypeShow();
// Вызывающая сторона
class MyClass {
// Объявляем делегат в классе
delegate int TypeDraw(string str);
public MyClass() {
// Создаем экземпляр класса с методами
DelegateTest delegateTest = new DelegateTest();
// Объявляем ссылки на объекты делегатов
TypeShow typeShow;
TypeDraw typeDraw;
// Создаем объекты делегатов
typeShow = new TypeShow(delegateTest.Show1);
typeDraw = new TypeDraw(delegateTest.Draw1);
// Вызываем методы посредством делегатов
typeShow();
typeDraw("int Draw1(string str1)");
// Адресуемся к другим методам с той же сигнатурой
typeShow = new TypeShow(delegateTest.Show2);
typeDraw = new TypeDraw(delegateTest.Draw2);
// Вызываем другие методы посредством делегатов
typeShow();
typeDraw("int Draw2(string str2)");
// Вызываем статический метод
// посредством подходящего делегата
typeDraw = new TypeDraw(DelegateTest.Print);
typeDraw("static int Print(string str)"); } }

// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = "Применение делегатов";
new MyClass(); // Чтобы сработал конструктор
} }

class DelegateTest    {      // Объявляем функции с сигнатурой делегатов

Слайд 7Многоадресная работа делегатов
Многоадресатная передача — это способность создавать список вызовов

(или цепочку вызовов) методов, которые должны автоматически вызываться при вызове

делегата.

Делегат с многоадресатной передачей имеет одно ограничение: он должен возвращать тип void.

Надо создать экземпляр делегата, а затем для добавления методов в эту цепочку использовать оператор "+=".
Для удаления метода из цепочки используется оператор " - = " .
Многоадресная работа делегатовМногоадресатная передача — это способность создавать список вызовов (или цепочку вызовов) методов, которые должны автоматически

Слайд 8// Для методов, имеющих одинаковую сигнатуру и не возвращающих значение

(только с void) с помощью делегата можно организовать сразу цепочку вызовов
class

MultiTest {
// Статическое поле
static int x = 1;
// Объявляем функции с одинаковой сигнатурой
public void Handler1(string name) {
Console.WriteLine(name + x++); }
public void Handler2(string name) {
Console.WriteLine(name + x++); }
public void Handler3(string name) {
Console.WriteLine(name + x++); } }
// Вызывающая сторона
class MyClass {
// Объявляем делегат в классе
delegate void TypeHandler(string text);
public MyClass() {
// Создаем экземпляр класса с методами
MultiTest obj = new MultiTest();
// Создаем объект-делегат и заполняем адресами
TypeHandler Handler = new TypeHandler(obj.Handler1);
Handler += new TypeHandler(obj.Handler2);
Handler += obj.Handler3; // Упрощенный синтаксис
// Вызываем цепочку методов
Handler("Вызов: Handler"); } }

// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = "Многоадресные делегаты";
new MyClass(); // Чтобы сработал конструктор
} }
// Для методов, имеющих одинаковую сигнатуру и не возвращающих значение (только с void) с помощью делегата можно организовать

Слайд 9Делегаты являются экземплярами типа System.MulticastDelegate, который в свою очередь наследует абстрактный

класс System.Delegate.

Экземпляр типа MulticastDelegate может хранить в себе одну или сразу несколько

ссылок на методы. В любом случае мы не можем явно объявлять делегат с помощью типа MulticastDelegate.

Это делается с помощью ключевого слова delegate, но неявно порождается объект класса MulticastDelegate.
Структура примера через панель Class View.
Делегаты являются экземплярами типа System.MulticastDelegate, который в свою очередь наследует абстрактный класс System.Delegate. Экземпляр типа MulticastDelegate может хранить в себе одну

Слайд 10Пустые делегаты
Делегат существует как объект до тех пор, пока его

список с адресуемыми функциями содержит хотя бы одну функцию.

Если

список делегата становится пустым, то он превращается в обычную ссылочную переменную с нулевой адресацией.

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

Если делегат имеет пустой список, т.е. не ссылается ни на одну функцию, то представляющая его ссылка имеет нулевой адрес

Пустые делегатыДелегат существует как объект до тех пор, пока его список с адресуемыми функциями содержит хотя бы

Слайд 11class MultiTest {
// Объявляем функции

одного прототипа
public void Handler1()

{
Console.WriteLine("Исполняется Handler1"); }
public void Handler2() {
Console.WriteLine("Исполняется Handler2"); }
public void Handler3() {
Console.WriteLine("Исполняется Handler3"); } }

// Вызывающая сторона
class MyClass {
// Для заголовка консольного окна
public static string Title = "Пустые делегаты“;
// Объявляем делегат как член класса
delegate void MyDelegate();
public MyClass() {
// Создаем экземпляр класса с методами
MultiTest obj = new MultiTest();
// Создаем объект-делегат и заполняем ссылками на функции
// Инициализируем первой ссылкой
MyDelegate del = new MyDelegate(obj.Handler1);
// Добавляем другие ссылки
del += obj.Handler2;
del += obj.Handler3;
// Вызываем цепочку методов
del();
Console.WriteLine();
// Извлекаем метод и опять вызываем цепочку методов
del -= obj.Handler1;
del();
Console.WriteLine();
// Извлекаем метод и опять вызываем цепочку методов
del = (MyDelegate)Delegate.Remove(del, new MyDelegate(obj.Handler2));
del();
Console.WriteLine();
// Извлекаем последний метод и пытаемся адресоваться к пустому делегату
del -= obj.Handler3;
//del(); // Будет выброшено исключение, нужно проверять!!!
if (del != null) {
del(); // Так все нормально!
}
else
Console.WriteLine("Список делегата исчерпан!"); } }

// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
} }
class MultiTest  {    // Объявляем функции одного прототипа    public void

Слайд 12Члены типа MulticastDelegate, унаследованные от Delegate

Члены типа MulticastDelegate, унаследованные от Delegate

Слайд 13//Применение свойства Method
class MultiTest {
//

Статическое поле
static int x = 1;

// Объявляем функции с одинаковой сигнатурой
public void Handler1() {
Console.WriteLine("Исполняется Handler1"); }
public void Handler2() {
Console.WriteLine("Исполняется Handler2"); }
public void Handler3() {
Console.WriteLine("Исполняется Handler3"); }
}

// Вызывающая сторона
class MyClass {
public static string Title = "Свойство Method“;
// Объявляем делегат как член класса
delegate void MyDelegate();
public MyClass() {
// Создаем экземпляр класса с методами
MultiTest obj = new MultiTest();
// Создаем объект-делегат и заполняем ссылками на функции
// Инициализируем первой ссылкой
MyDelegate del = new MyDelegate(obj.Handler1);
// Добавляем другие ссылки
del += obj.Handler2;
del += obj.Handler3;
// Вызываем цепочку методов
del();
Console.WriteLine();
del.Method.Invoke(obj, null); // Вызываем последний метод
Console.WriteLine("\nПрототип последнего метода:\n{0}",
del.Method.ToString());
Console.WriteLine("\nИмена адресуемых методов:");
Delegate[] listMethods = del.GetInvocationList();
for (int i = 0; i < listMethods.Length; i++)
Console.WriteLine("{0}", listMethods[i].Method.Name); } }

// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
} }
//Применение свойства Methodclass MultiTest  {    // Статическое поле    static int

Слайд 14//Свойство Target - свойство возвращает объект, связанный с адресуемым делегатом

методом
class MultiTest {
// Объявляем функции

с одинаковой сигнатурой
public void Handler1() {
Console.WriteLine("Исполняется Handler1"); }
public void Handler2() {
Console.WriteLine("Исполняется Handler2"); }
public void Handler3() {
Console.WriteLine("Исполняется Handler3"); } }
// Вызывающая сторона
class MyClass {
public static string Title = "Применение свойства Target делегата";
// Объявляем делегат как член класса
delegate void MyDelegate();
public MyClass() {
// Создаем экземпляр класса с методами
MultiTest obj = new MultiTest();
// Создаем объект-делегат и заполняем ссылками на функции
// Инициализируем первой ссылкой
MyDelegate del = new MyDelegate(obj.Handler1);
// Добавляем другие ссылки
del += obj.Handler2; del += obj.Handler3;

// Вызываем цепочку методов
Console.WriteLine("Многоадресный вызов через делегат");
del();
Console.WriteLine();
// Возвращает объект, с которым связан
// последний адресуемый метод
Console.WriteLine("Тип объекта: {0}",
del.Target.GetType().ToString());
Console.WriteLine();
// Повышаем полномочия извлеченной из Target ссылки
// на объект и повторно адресуемся напрямую
Console.WriteLine("Вызов через свойство Target делегата");
((MultiTest)del.Target).Handler1();
((MultiTest)del.Target).Handler2();
((MultiTest)del.Target).Handler3();
Console.WriteLine();
// Адресуемся напрямую без делегата
Console.WriteLine("Вызов через объект напрямую");
obj.Handler1(); obj.Handler2();
obj.Handler3(); } }



//Свойство Target - свойство возвращает объект, связанный с адресуемым делегатом методомclass MultiTest  {

Слайд 15
// Запуск
class Program {

static void Main() {

// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
} }

// Запуск  class Program  {    static void Main()    {

Слайд 16Методы DynamicInvoke() и GetInvocationList()
Позволяют вызывать отдельные члены, адресуемые списком объекта-делегата,

и задавать требуемые аргументы.

Если член списка не имеет аргументов,

то в качестве параметра метода используется null, иначе - массив параметров адресуемого члена.

Объявление ссылки на объект-делегат прописывает только прототип методов, которые корректно может адресовать эта ссылка.

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

Методы DynamicInvoke() и GetInvocationList()Позволяют вызывать отдельные члены, адресуемые списком объекта-делегата, и задавать требуемые аргументы. Если член списка

Слайд 17class ShowPerson {
// Объявляем функцию

с аргументами
public static void Handler(string name,

int age) {
Console.WriteLine("Сотрудник {0}, возраст {1}", name, age); } }
// Вызывающая сторона
class MyClass {
public static string Title = "Вызов методов с параметрами”;
// Объявляем делегат как член класса
delegate void MyDelegate(string name, int age);
public MyClass() {
// Создаем и заполняем объект-делегат
MyDelegate del = new MyDelegate(ShowPerson.Handler);
// Добавляем другие ссылки
int count = 3;
for (int i = 1; i < count; i++) {
del += ShowPerson.Handler; }
// Вызываем цепочку методов с одинаковым параметром
del("Иванов", 21); } }

// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
} }

все зарегистрированные в делегате методы стороннего класса получают, при вызове их с помощью делегата, одинаковую входную информацию

class ShowPerson  {    // Объявляем функцию с аргументами    public static

Слайд 18если с помощью делегата нужно адресовать методы, имеющие разные значения

параметров используется
public object DynamicInvoke(params object[ ] args)

с помощью метода DynamicInvoke() можно

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

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

Эти проблемы решает метод DynamicInvoke() совместно с GetInvocationList()


если с помощью делегата нужно адресовать методы, имеющие разные значения параметров используетсяpublic object DynamicInvoke(params object[ ] args)с

Слайд 19class ShowPerson {
// Функция с

аргументами
public static void Handler(string name, int

age) {
Console.WriteLine("Сотрудник {0}, возраст {1}", name, age); }
// Проблемная функция с нормальным прототипом
public static void ProblemHandler(string name, int age) {
// Преднамеренно выбрасываем исключение
throw new Exception(); } }
// Вызывающая сторона
class MyClass {
public static string Title = "Применение DynamicInvoke()“;
// Объявляем делегат
delegate void MyDelegate(string name, int age);
public MyClass() {
// Формируем список объекта-делегата
// Добавляем в список один проблемный метод
MyDelegate del = new MyDelegate(ShowPerson.ProblemHandler);
// Добавляем еще три нормальных метода
int count = 3;
for (int i = 0; i < count; i++)
{ del += ShowPerson.Handler; }
object[] param = new object[2]; // Объявили массив для параметров
int j = 0; // Объявили и инициализировали счетчик
// Перебираем список вызовов делегата, включая и вызов проблемного метода
foreach (Delegate d in del.GetInvocationList()) {
// Индивидуально формируем параметры методов
switch (j) {
case 0: // Можно и не задавать, все равно для проблемного метода!
param[0] = "Мистер X";
param[1] = 99; break;
// Для вызовов нормального метода
case 1: param[0] = "Иванов";
param[1] = 21; break;
case 2: param[0] = "Петров";
param[1] = 22; break;
case 3: param[0] = "Сидоров";
param[1] = 23; break; }
j++; // Счетчик
// Защищено вызываем адресуемые методы индивидуально
try {
d.DynamicInvoke(param); }
catch (Exception exc) {
string str = d.Method.Name;
Console.WriteLine("Сбой метода {0}!!!", str);
str = exc.Message; // Системное сообщение
// Разбиваем длинное сообщение пополам
int pos = str.Length / 2;
pos = str.IndexOf(' ', pos); // От средины первый пробел
Console.WriteLine("\"" + // Экранируем кавычки
str.Substring(0, pos) + Environment.NewLine + str.Substring(pos + 1) + "\""); // Экранируем кавычки
Console.WriteLine(); // Отделяем сообщение
} } } }



class ShowPerson  {    // Функция с аргументами    public static void

Слайд 20
// Запуск
class Program
{

static void Main()
{

// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
}
}
// Запуск  class Program  {    static void Main()

Слайд 21Перегруженные операторы 'operator ==' и 'operator !='
Эти операторы позволяют подтвердить

или опровергнуть абсолютную идентичность списков функций сравниваемых делегатов.

Перегруженные операторы 'operator ==' и 'operator !='Эти операторы позволяют подтвердить или опровергнуть абсолютную идентичность списков функций сравниваемых

Слайд 22class Handler {
// Функции

public void Handler1() {

}
public void Handler2() { ; }
}
// Вызывающая сторона
class MyClass {
public static string Title = "Применение операторов '==' и '!='";
// Объявляем делегат
delegate void MyDelegate();
// Объявляем ссылки на делегаты как
// поля для видимости в методах класса
MyDelegate del0, del1;
public MyClass() {
// Создаем объект
Handler obj = new Handler();
// Формируем список вызовов объекта-делегата
del0 = new MyDelegate(obj.Handler1);
del0 += new MyDelegate(obj.Handler2);
// Еще один делегат с тем же списком вызовов
del1 = new MyDelegate(obj.Handler1);
del1 += obj.Handler2; // Упрощенный синтаксис
// Сравниваем делегаты с полностью совпадающими списками
Compare();
// Делегат прежним содержимым, но в другом порядке
del1 = new MyDelegate(obj.Handler2);
del1 += obj.Handler1; // Упрощенный синтаксис
// Сравниваем делегаты с одинаковым содержимым, но разным порядком
Compare();
// Изменяем содержимое одного из делегатов
del0 -= obj.Handler2;
// Опять сравниваем делегаты с разным содержимым
Compare(); }
void Compare() {
if (del0 == del1)
Console.WriteLine("Списки делегатов идентичны");
else
Console.WriteLine("Списки делегатов различны"); } }
// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = MyClass.Title;
new MyClass(); // Исполняем
} }

Слайд 42class MyClass {// Получатель сообщения
//

Конструктор
public MyClass()

{
// Создаем объект, имеющий событие
SourceEvent obj = new SourceEvent();
// Подписываемся на обработчики события
obj.Event += new EventHandler(Handler1);
obj.Event += new EventHandler(Handler2);
// Вызываем симулятор возникновения события
obj.SimulateEvent(); }
void Handler1(object sender, EventArgs e) {
// Хотим извлечь информацию из толстого объекта,
// значит нужно повысить полномочия тонкой ссылки
MyEventArgs args = (MyEventArgs)e;
String message = args.Message;
Console.WriteLine("(Handler1) Получена информация:\n" + message);
Console.WriteLine(); }
void Handler2(object sender, EventArgs e) {
Console.WriteLine("(Handler2) Событие из объекта {0}\n" + "Передан объект-аргумент {1}”, sender.GetType().Name, e.GetType().Name);
} }
// Запуск
class Program {
static void Main() {
// Настройка консоли
Console.Title = "Применение делегата EventHandler";
new MyClass(); // Исполняем
} }
class MyClass  {// Получатель сообщения    // Конструктор    public MyClass()

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика