Делегат для выбора методов на этапе выполнения

Использование делегатов

Существует 4 вида использования делегатов:

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

2. Делегат – оповещатель наблюдателя (паттерн “наблюдатель”);

3. Делегат, как обратный вызов метода;

4. Делегат, как обработчик событий. Обычно события обрабатываются не простыми методами, а делегатами. Событие генерирует идею “произошло нечто важное”, и программа должна на него отреагировать. События и делегаты являются тесно связанными понятиями, поскольку обработка событий требует точного выбора обработчика. Обработчик события реализуется на языке С#, как правило, в виде делегата.

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

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

 

 

Delegate.Invoke или что там внутри? (для продвинутых)

Метод Invoke недокументирован. Он не является членом классов Delegate и MulticastDelegate. Соответственно, можно предположить, что это специальный метод, генерируемый компилятором. Его изучение показывает, что метод лишен какого-либо кода. Он попросту пустой и ничего не может делать. Так может показаться, если не принимать во внимание спецификатор runtime, используемый при определении метода. Данный спецификатор указывает на то, что метод будет реализован по ходу исполнения программы самой средой исполнения. Это означает, что код, обрабатывающий вызов метода, располагается в недрах самой среды исполнения. А она прекрасно осведомлена о внутреннем устройстве делегата и справится с вызовом всех его методов без дополнительной помощи со стороны программиста.

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