сигнатуры (с возвращаемым типом) метода, который содержит делегат.
Основное использование делегатов состоит в передаче и вызове ссылок на методы: ссылки на методы нельзя передавать непосредственно, но они могут передаваться внутри делегата. Делегат обеспечивает безопасность типа данных, не позволяя вызывать метод с неверной сигнатурой. Метод, который содержит делегат, может вызываться синтаксически как вызов делегата. Следующий код показывает общие принципы. Первое, необходимо определить класс делегата:
// определить класс делегата, который представляет метод,
// получающий int и возвращающий void
delegate void MyOp(int X);
Затем, для целей этого примера объявим класс, который содержит вызываемый метод:
// затем определение класса
class MyClass {
void MyMethod(int X) {
// и т.д.
}
}
Еще позже, может быть при реализации некоторого другого класса, имеется метод, которому должна быть передана ссылка на метод с помощью делегата:
void MethodThatTakesDelegate(MyOp Op) {
// вызвать метод, передавая ему значение 4
Oр(4);
}
// и т.д.
И, наконец, код, который реально использует делегата:
MyClass Mine = new MyClass();
// Создать экземпляр делегата MyOp. Настроить его,
// чтобы он указывал на метод MyMethod из Mine.
MyOp DoIt = new MyOp(Mine.MyMethod);
После объявления переменной делегата можно вызвать метод с помощью делегата:
DoIt();
Или передать его в другой метод:
MethodThatTakesDelegate(DoIt);
В частном случае, когда делегат представляет метод, который возвращает void
, этот делегат является широковещательным делегатом и может одновременно представлять более одного метода. Вызов делегата заставляет все методы вызываться по очереди. Можно использовать операторы +
и +=
для добавления метода делегату, а -
и - =
— для удаления метода, который уже находится в делегате. Делегаты рассматриваются более подробно в главе 6.
События
События являются специальной формой делегатов, которые используются для поддержки модели уведомления о событии с помощью обратного вызова. Событие имеет следующую сигнатуру:
delegate void EventClass(obj Sender, EventArgs e);
Это сигнатура, которую должен иметь любой обработчик событий с обратным вызовом. Ожидается, что Sender
будет ссылкой на объект, который инициирует событие, в то время как System.EventArgs
(или любой класс, производный из EventArgs
, который также допустим в качестве параметра) является классом, используемым средой выполнения .NET для передачи базовой информации, имеющей отношение к деталям события.
Для объявления события используется специальный синтаксис:
public event EventClass OnEvent;
Клиенты используют синтаксис +=
широковещательных делегатов для информирования, что они хотят получить уведомление.
// EventSource ссылается на экземпляр класса, который содержит событие
EventSource.OnEvent += MyHandler;
Источник просто вызывает событие, когда потребуется, используя такой же синтаксис, который был показан выше для делегатов. Так как событие является широковещательным делегатом, то все обработчики событий будут вызваны в ходе этого процесса. События рассматриваются более подробно в главе 6.
OnEvent(this, new EventArgs());
Атрибуты
Концепция атрибутов не имеет эквивалента в ANSI C++, однако атрибуты поддерживаются компилятором Microsoft C++ как специальное расширение Windows. В версии C# имеются классы .NET, которые выводятся из System.Attribute
. Они могут применяться к различным элементам кода C# (классам, перечислениям, методам, параметрам и т.д.) для создания дополнительной документирующей информации в компилированной сборке. Кроме того, некоторые атрибуты распознаются компилятором C# и будут иметь влияние на компилированный код. Они включают следующие:
Атрибут | Описание |
---|---|
DllImport | Указывает, что метод определен во внешней DLL. |
StructLayout | Позволяет расположить содержимое структуры в памяти. Позволяет получить эквивалент union в C#. |
Obsolete | Создает ошибку компилятора или предупреждение, если используется этот метод. |
Conditional | Заставляет выполнить условную компиляцию. Этот метод и все ссылки на него будут игнорироваться, если присутствует определенный символ препроцессора. |
Существует большое число других атрибутов, а также возможно задать свои собственные специальные атрибуты. Использование атрибутов рассматривается в главах 6 и 7.