Добро пожаловать в Forum.iCoder.Uz

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

Задать вопрос

Задавайте вопросы и получайте ответы от нашего сообщества

Отвечать

Отвечайте на вопросы и станьте экспертом в своей теме

Связаться с нами

Наши специалисты готовы ответить на ваши вопросы

C# Делегаты

Информация о теме

О теме Здравствуйте, вы читаете тему Делегаты созданную в в разделе Обучение C# пользователем Deimos#. Эта тема была просмотрена 1 056 раз(а), получила 0 комментариев и 1 очки реакции...
Название категории Обучение C#
Название темы Делегаты
Автор темы Deimos#
Дата начала
Ответы
Просмотры
Количество реакций к первому сообщению
Последнее сообщение Deimos#

Deimos#

Модератор #2
Регистрация
17.02.2016
Сообщения
116
Реакции
46
Баллы
35
Возраст
31
Адрес
Россия
Всем доброго времени суток
В Microsoft.NET Framework этот механизм поддерживается при помощи делегатов (delegates).
В отличие от других платформ, например неуправляемого языка C++, делегаты обладают более широкой функциональностью.
Например, они обеспечивают безопасность типов при выполнении обратного вызова (способствуя решению одной из важнейших задач CLR).
Кроме того, они обеспечивают возможность последовательного вызова нескольких методов, а также вызова как статических, так и экземплярных методов.

Знакомство с делегатами
В Windows механизм обратного вызова используется оконными процедурами, процедурами перехвата, асинхронным вызовом процедур и др. В .NET Framework методы обратного вызова также имеют многочисленные применения. К примеру, можно зарегистрировать такой метод для получения различных уведомлений: о необработанных исключениях, изменении состояния окон, выборе пунктов меню, изменениях файловой системы и завершении асинхронных операций.
В .NET Framework функции обратного вызова играют не менее важную роль, чем при неуправляемом программировании для Windows. Однако данная платформа
предоставляет в распоряжение разработчика делегатов — механизм, безопасный по отношению к типам.
Рассмотрим пример объявления, создания и использования делегатов:
C#:
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержимого кодов!
Вывод результата работы программы
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержания URL!

Рассмотрим этот код более подробно. Прежде всего следует обратить внимание на объявление внутреннего делегата Feedback .
Он задает сигнатуру метода обратного вызова. Данный делегат определяет метод, принимающий один параметр типа Int32 и возвращающий значение void .
Он напоминает ключевое слово typedef из C/C++, которое предоставляет адрес функции.
Класс Program определяет закрытый статический метод Counter . Он перебирает целые числа в диапазоне, заданном аргументами from и to.
Также он принимает параметр fb , который является ссылкой на делегат Feedback .
Метод Counter перебирает числа в цикле и для каждого из них при условии, что переменная fb не равна null ,
выполняет метод обратного вызова (определенный переменной fb ). При этом методу обратного вызова передается значение обрабатываемого элемента и его номер.
Реализация данного метода может обрабатывать элементы так, как считает нужным.

Обратный вызов статических методов
Теперь, когда мы разобрали принцип работы метода Counter, рассмотрим процедуру использования делегатов для вызова статических методов.
Для примера возьмем метод StaticDelegateDemo из представленного в предыдущем разделе кода.
Метод StaticDelegateDemo вызывает метод Counter , передавая в третьем параметре fb
значение null . В результате при обработке элементов не задействуется метод обратного вызова.
При втором вызове метода Counter методом StaticDelegateDemo третьему параметру передается только что созданный делегат Feedback .
Этот делегат служит оболочкой для другого метода, позволяя выполнить обратный вызов последнего косвенно, через оболочку.
В рассматриваемом примере имя статического метода Program.FeedbackToConsole передается конструктору Feedback ,
указывая, что именно для него требуется создать оболочку. Возвращенная оператором new ссылка передается третьему параметру метода Counter ,
который в процессе выполнения будет вызывать статический метод FeedbackToConsole . Последний же просто выводит на консоль строку с названием обрабатываемого элемента.

Третий вызов метода Counter внутри метода StaticDelegateDemo отличается от второго тем, что делегат Feedback
является оболочкой для статического метода Program.FeedbackToMsgBox . Именно метод FeedbackToMsgBox создает строку,
указывающую на обрабатываемый элемент, которая затем выводится в окне в виде сообщения.
В этом примере ничто не нарушает безопасность типов. К примеру, при создании делегата Feedback компилятор убеждается в том,
что сигнатуры методов FeedbackToConsole и FeedbackToMsgBox типа Program совместимы с сигнатурой делегата.
Это означает, что оба метода будут принимать один и тот же аргумент

(типа Int32 ) и возвращать значение одного и того же типа ( void ).
Однако попробуем определить метод FeedbackToConsole вот так:
C#:
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержимого кодов!
В этом случае компилятор выдаст сообщение об ошибке (сигнатура метода FeedbackToConsole не соответствует типу делегата):
Код:
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержимого кодов!
Как C#, так и CLR
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержания URL!
при привязке метода к делегату.
Ковариантность (covariance) означает,что метод может возвратить тип, производный от типа, возвращаемого делегатом.
Контравариантность (contra-variance) означает, что метод может принимать параметр,
который является базовым для типа параметра делегата. Например:
C#:
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержимого кодов!
Определив делегат таким образом, можно получить экземпляр этого делегата,связанный с методом, прототип которого выглядит примерно так:
C#:
Пожалуйста, Войдите или Зарегистрируйтесь для просмотра содержимого кодов!
Здесь тип значения, возвращаемого методом SomeMethod
(тип String ), является производным от типа, возвращаемого делегатом ( Object );
такая ковариантность разрешена.
Тип параметра метода SomeMethod
(тип Stream ) является базовым классом для типа параметра делегата ( FileStream );
такая контравариантность тоже разрешена.
Обратите внимание, что ковариантность и контравариантность поддерживаются только для ссылочных типов,
но не для значимых типов или значения void


Обратный вызов экземплярных методов
Обратите внимание, что объект p типа Program создается внутри метода InstanceDelegateDemo .
При этом у него отсутствуют экземплярные поля и свойства,поскольку он сконструирован с демонстрационными целями.
Когда при вызове метода Counter создается делегат Feedback , его конструктору передается объект
p.FeedbackToFile . В результате делегат превращается в оболочку для ссылки на метод FeedbackToFile ,
который является не статическим, а экземплярным методом.
Когда метод Counter обращается к методу обратного вызова, который задан аргументом fb ,
вызывается экземплярный метод FeedbackToFile , а адрес только что созданного объекта
p передается этому методу в качестве неявного аргумента this.
Как видите, делегаты могут служить оболочкой как для статических, так и для экземплярных методов.​
В последнем случае делегат должен знать, какой экземпляр объекта будет обрабатывать вызываемый им метод.
Создавая оболочку для экземплярного метода, вы предоставляете коду внутри объекта доступ к различным
членам экземпляра объекта. Это означает наличие у объекта состояния, которое может использоваться во время выполнения метода обратного вызова.

Спасибо за внимание
 
Последнее редактирование:
shape1
shape2
shape3
shape4
shape7
shape8
Сверху Снизу