Определение делегата в C#
Определение делегата в C#
Чтобы создать делегат в C#, вы должны использовать ключевое слово delegate. Имя делегата может быть любым. Однако делегат должен соответствовать методу, на который этот делегат будет указывать. Предположим, например, что нам нужно создать делегат с именем BinaryOp, который сможет указывать на любой метод, возвращающий целое число и имеющий целочисленные входные параметры.
// Этот делегат может указывать на любой метод,
// принимающий два целых значения
// и возвращающий целое значение.
public delegate int BinaryOp(int x, int y);
При обработке типов делегата компилятор C# автоматически генерирует изолированный класс, являющийся производным от System.MulticastDelegate. Этот класс (вместе с базовым классом System.Delegate) обеспечивает делегату необходимую инфраструктуру, позволяющую поддерживать список методов, которые должны быть вызваны позднее. Например, если рассмотреть содержимое делегата BinaryOp с помощью ildasm.exe, вы увидите элементы, показанные на рис. 8.2.

Рис. 8.2. Ключевое слово delegate в C# представляет изолированный тип, производный от System.MulticastDelegate
Как видите, генерируемый здесь класс BinaryOp определяет три открытых метода. Метод Invoke() можно назвать главным, поскольку он используется для синхронного вызова методов, поддерживаемых типом делегата, и синхронность здесь означает то, что вызывающая сторона для продолжения работы должна ожидать завершения вызова. Весьма странным кажется тот факт, что синхронный метод Invoke() в C# нельзя вызвать непосредственно. Чуть позже будет продемонстрировано, как Invoke() вызывается опосредованно с помощью соответствующей синтаксической конструкции.
Методы BeginInvoke() и EndInvoke() обеспечивает возможность асинхронного вызова текущего метода во вторичном потоке выполнения. Если у вас есть опыт работы с многопоточными приложениями, вы должны знать, что одной из главных причин, по которым разработчики создают вторичные потоки, является вызов методов, для выполнения которых требуется много времени. И хотя библиотеки базовых классов .NET предлагают целое пространство имен (System.Threading), специально предназначенное для решения задач многопоточного программирования, с помощью делегатов соответствующие функциональные возможности использовать проще.
Но откуда компилятор "знает", как определять методы Invoke(), BeginInvoke() и EndInvoke()? Чтобы понять суть процесса, рассмотрим пример автоматически генерируемого типа класса BinаrуОр (полужирным шрифтом здесь обозначены элементы, заданные определяемым типом делегата).
sealed class BinaryOp: System.MulticastDelegate {
public BinaryOp(object target, uint functionAddress);
public void Invoke(int x, int y);
public IAsyncResult BeginInvoke(int x, int y, AsyncCallback cb, object state);
public int EndInvoke(IAsyncResult result);
}
Во-первых, обратите внимание на то, что параметры и возвращаемое значение определяемого здесь метода Invoke() соответствуют определению делегата BinaryOp. Первые параметры членов BeginInvoke() (в данном случае это два целых числа) тоже соответствуют определению делегата BinaryOp, однако BeginInvoke() всегда имеет еще два параметра (типа AsyncCallback и object), которые используются для асинхронного вызова методов. Наконец, возвращаемое значение метода EndInvoke() тоже соответствует исходной декларации делегата, а единственным параметром метода является объект, реализующий интерфейс IAsyncResult.
Рассмотрим еще один пример. Предположим, что мы определили тип делегата, который позволяет указать на любой метод, возвращающий строку и имеющий три входных параметра System.Boolean.
public delegate string MyDelegate(bool a, bool b, bool c);
На этот раз автоматически генерируемый класс выглядит так.
sealed class MyDelegate : System.MulticastDelegate {
public MyDelegate(object target, uint functionAddress);
public string Invoke(bool a, bool b, bool c);
public IAsyncResult BeginInvoke(bool a, bool b, bool c, AsyncCallback cb, object state);
public string Endlnvoke(IAsyncResult result);
}
Делегаты могут также "указывать" на методы, содержащие любое число параметров out или ref. В качестве примера рассмотрим следующий тип делегата.
public delegate string MyOtherDelegate(out bool a, ref bool b, int c);
Сигнатуры методов Invoke() и BeginInvoke() выглядят так, как и ожидается, но обратите внимание на метод EndInvoke(), который теперь включает и все аргументы out/ref, определенные типом делегата.
sealed class MyOtherDelegate : System.MulticastDelegate {
public MyOtherDelegate (object target, uint functionAddress);
public string Invoke(out bool a, ref bool b, int c);
public IAsyncResult BeginInvoke(out bool a, ref bool b, int c, AsyncCallback cb, object state);
public string EndInvoke(out bool a, ref bool b, IAsyncResult result);
}
Итак, в результате определения делегата в C# компилятор генерирует изолированный класс с тремя методами, для которых возвращаемые значения и типы параметров соответствуют декларации делегата. Следующий псевдокод приближенно описывает соответствующий базовый шаблон.
// Это только псевдокод!
public sealed class ИмяДелегата : System.MulticastDelegate {
public ИмяДелегата(object target, uint functionAddress);
public возвращаемоеЗначениеДелегата Invoke(всеПараметрыДелегата);
public IAsyncResult BeginInvoke(всеПараметрыДелегата, AsyncCallback cb, object state);
public возвращаемоеЗначениеДелегата EndInvoke(всеПараметрыRefOutДелегата, IAsyncResult result);
}
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Определение
Определение Инструменты компонентного тестирования в большей степени, чем какие-либо другие инструменты, выражают наше представление о том, что понимать под «выполненной» работой. Когда бизнес-аналитики и специалисты по контролю качества создают спецификацию,
4.1.1 Определение
4.1.1 Определение Индексы существуют на диске в статической форме и ядро считывает их в память прежде, чем начать с ними работать. Дисковые индексы включают в себя следующие поля:• Идентификатор владельца файла. Права собственности разделены между индивидуальным
Определение IP по ICQ
Определение IP по ICQ Чтобы определить IP того, кто общается с вами посредством ICQ, достаточно воспользоваться программой UIN2IP (http://neptunix.narod.ru/uin.htm).Вот список некоторых функций UIN2IP:– автоматическое обновление листа;– автоматическое копирование IP-адреса в буфер при двойном
3.6.1. Определение ограничений
3.6.1. Определение ограничений Для определения (задания) ограничений используется команда edquota. Ограничение дискового пространства пользователя производится командой edquota с параметром –u (см. рис. 3.7), а определение квот для группы — с параметром –g. После выполнения этой
2.2.1. Определение
2.2.1. Определение В общем смысле, контекстная реклама – это вид интернет-рекламы, демонстрируемой человеку в зависимости от содержимого интернет-страницы, на которой она расположена. Например, объявление о продаже автомобиля на сайте об автомобилях, реклама сотовых
Определение y-параметров
Определение y-параметров Базовые уравнения для определения параметров проводимости четырехполюсника:I1 = y11V1 + y12V2;I2 = y21V1 + y22V2. Рис. 12.1. Четырехполюсник На рис. 12.1 представлен четырехполюсник с условными направлениями токов и напряжений. Проводимости в сомножителях,
Тип делегата .NET
Тип делегата .NET Перед тем как дать формальное определение делегата .NET, давайте обсудим соответствующие перспективы. В Windows API для создания объектов, называемых функциями обратного вызова, предполагается использовать указатели функций (подобные указателям C). Используя
Простейший пример делегата
Простейший пример делегата В начале освоения приемов работы с делегатами у программиста может возникать много вопросов. Поэтому мы начнем с рассмотрения очень простого примера, в котором используется созданный нами тип делегата BinaryOp. Вот программный код, который мы
Исследование объекта делегата
Исследование объекта делегата Добавим в имеющийся пример вспомогательную функцию с именем DisplayDelegateInfo(). Она будет выводить имена методов, поддерживаемых поступающим типом, производным от System.Delegate, а также имя класса, определяющего метод. Для этого мы выполним цикл по
Более совершенный пример делегата
Более совершенный пример делегата Чтобы продемонстрировать более интересные варианты использования делегатов, мы добавим в класс Car пару членов-переменных логического типа. Первый из добавляемых членов предназначен для индикации того, что автомобиль необходимо помыть
Роль делегата AsyncCallback
Роль делегата AsyncCallback Вместо того чтобы выяснять у делегата, завершился ли асинхронный вызов метода, лучше позволить делегату информировать поток вызова о выполнении задания. Чтобы реализовать такое поведение, вы должны предъявить экземпляр делегата System.AsyncCallback методу
Определение платформы
Определение платформы Если нужно определить, на какой платформе запущено ваше приложение, то здесь вам не обойтись без вызова функции Windows API SystemParametersInfo.Для начала нужно создать новый класс PlatformDetector, в котором следует объявить функцию SystemParametersInfo и методы определения
Определение диаметра
Определение диаметра Диаметр можно проставить с помощью команды DIMDIAMETER. Эту команду можно вызвать, нажав на стрелку справа от кнопки Linear (Линейный) на вкладке Annotate (Аннотация) в группе Dimensions (Размеры), а затем выбрав способ задания размеров Diameter (Диаметр).Рассмотрим вставку
Определение нотации
Определение нотации С точки зрения физической модели, XML-документы являются не более чем текстом. Содержимое документов и их разметка имеет исключительно текстовый вид. Вместе с тем, во многих случаях документы должны включать данные других форматов, например,