Главная » C# » Объявление делегата и использование методов расширения в Visual C# (Sharp)

0

Делега т  объявляетс я  в  перво й  строк е  кода :

public delegate void ProcessValue(int value);

Объявлени е   делегат а   находитс я    вн е   област и   видимост и   класс а   ил и    интерфейса , н о   делега т   долже н   использоватьс я   в   контекст е   класса .   Поэтом у   в   т о   врем я   ка к

для объявления делегата не требуется окружающий тип, то для его реализации требуется.

Типом делегата является идентификатор метода, которым в нашем случае выстает ProcessValue. Делегат будет использован в примере для предоставления оего механизма обратных вызовов в итераторе.  Итератор  объявляется  следуим образом:

public static class Extensions {

public static void Iterate(this IList<int> collection,

ProcessValue cb) { foreach (int element in collection) {

cb(element);

}

}

}

Статический  класс  Extensions имеет  статический  метод.  Как  было  объяснено в главе 4, это означает, что для данного класса никогда нельзя создавать экземплов, а вызов метода iterate*)  выполняется следующим способом:

Extensions.Iterate(…);

В первом  параметре методу iterate*) передается список для обработки в цикле, а во втором — экземпляр делегата. Обратите внимание на то, что первый параметр объявлен с ключевым словом this . Представьте, что метод объявлен без использания этого ключевого слова и используется как статический метод. Вызывающая структура будет выглядеть таким образом:

IList<int> collection;  ProcessValue cb; Extensions.Iterate(collection, cb);

Этот код несколько неуклюж, т. к. в нем ясно  подразумевается  необходимость знать о существовании метода, обрабатывающего список. Было бы лучше, если бы могли сначала объявить список, а потом использовать IntelliSense, чтобы узнать, имеется ли данный метод. В С# версии 3.0 это возможно посредством методов расширения,  которые позволяют разработчику создавать методы,  ассоциированные с классами, иными, чем те, в которых они были объявлены. В контексте текущего примера методы расширения позволяют написать следующий код:

IList<int> collection; ProcessValue cb; collection.Iterate(cb);

Метод iterate () кажется расширением IList, при этом модифицировать IList не требуется. Методы расширения объявляются  посредством объявления статическо класса со статическим методом, первому параметру которого предшествует ключевое слово this. Этот параметр не требуется в вызове метода, но представляет тип, который нужно расширить.

ПРИМЕЧАНИЕ

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

.NET, таких как int, double или IList, или если изменение типов потребовало бы слишком много усилий и времени. Методы расширения применяются только ради функциональности,  повторно  используемой  по  всему  коду.  Их  можно  было  применить в одном или двух случаях, но в долгосрочном плане это может оказаться проблемичным  по  причине возможных перекрытий  или  конфликтов.

В реализации метода iterate* ) каждый элемент коллекции обрабатывается в цие foreach, в котором переменная cb вызывается, как будто бы она была методом. Вызов переменной cb отделяет итератор от обработки итерации цикла. Представьте себе метод для вычисления текущей общей суммы или максимального значения нескольких значений. Для обработки в цикле элементов нам нужно было бы вызом метода создать экземпляр делегата и вызвать метод iterate* ) следующим образом:

1st.Iterate(new ProcessValue(ProcessRunningTotal));

1st. Iterate (new ProcessValue (ProcessMaximumValue)) ,-

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

Источник: Гросс  К. С# 2008:  Пер. с англ. — СПб.:  БХВ-Петербург, 2009. — 576 е.:  ил. — (Самоучитель)

По теме:

  • Комментарии