Главная » C# » Реализация делегата в Visual C# (Sharp)

0

Реализация делегата является  простым  процессом.  Нужно только  объявить  метод в  классе,  который  имеет такую же сигнатуру метода.  Делегат  можно  реализовать с  помощью  статического  метода  или  метода  экземпляра;  разницы  нет  никакой. В следующем коде демонстрируется реализация делегата ProcessValue на основе обоих видов методов,

class Delegatelmplementations  {  void InstanceProcess(int value) { }

static void StaticProcess(int value) { }

public static ProcessValue Staticlnstantiate() { return new ProcessValue(StaticProcess);

}

public ProcessValue Instancelnstantiate() { return new ProcessValue(InstanceProcess);

}

}

В примере методы InstanceProcess*) и StaticProcess*) являются реализациями делегата ProcessValue. Делегат не имеет никаких ассоциаций. При реализации мода интерфейса класса мы знаем, какие методы каким интерфейсам принадлежат.

С делегатами такого везения у нас нет. Если у нас имеются два делегата с одинакыми сигнатурами параметров и возвращаемого типа, тогда метод с такой же сиатурой можно использовать для определения любого делегата.

Чтобы методы распознавались как делегаты, необходимо взглянуть на методы Staticlnstantiate () и Instancelnstantiate (). Каждый метод создает экземпляр делегата с помощью ключевого слова new, и каждый экземпляр имеет один паретр конструктора, являющийся методом, который нужно ассоциировать с экземплом делегата. Обратите внимание на то, каким образом метод staticlnstantiate о создает экземпляр делегата с методом staticProcess (). Это возможно потому, что оба  метода  являются  статическими.  Так  как  статические  методы  преобразуются в делегаты, не играет роли,  сколько  раз  создается  экземпляр делегата — каждый раз вызывается один и тот же экземпляр метода.

В реализации метода instancelnstantiate*) создается делегат, который служит оберткой для метода instanceProcess (). С первого взгляда может показаться, что поведени е методо в Instancelnstantiate() и Statelnstantiate() СХОДНО, НО меж – ду этими  двумя  способами  создания  экземпляра  существует  большая  разница. А именно, чтобы выполнить метод instancelnstantiate!), необходимо создать экземпляр Delegate implementations. Это очень важный аспект, который нужно принимать во внимание. Рассмотрим следующий исходный код, в котором исполуется экземпляр Delegatelmplemen tat ions,

public ProcessValue GetMeADelegate() {  Delegatelmplementations els = new Delegatelmplementations();

return els.Instancelnstantiate();

}

В реализации GetMeADelegate () создается экземпляр класса Delegatelmplementations и вызывается метод instancelnstantiate о. Так как область  видимости объекта els ограничена методом GetMeADelegate*), может показаться, что сборка мусора для этого объекта выполняется после завершения  исполнения  метода.  Но  это  не так. При вызове метода instancelnstantiate!) создается экземпляр делегата, корый ссылается на метод instanceProcess <). Поэтому, хотя делегат ссылается на метод, на экземпляр класса els существует ссылка, что препятствует выполнению сборки мусора для него.

ПРИМЕЧАНИЕ

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

Теперь посмотрим, как можно реализовать делегаты в примере с вычислением тущей суммы и максимального значения:

static class Tests {  static int „runningTotal;

static void ProcessRunningTotal(int value) {

_runningTotal += value;

}

static int _maxValue;

static void ProcessMaximumValue(int value) { if (value > _maxValue) {

_maxValue = value;

}

}

}

Методы ProcessRunningTotal () и ProcessMaximumValue () имеют одну И ту же сигнатуру  ProcessValue(),  поэтому  являются  кандидатами  на   создание делегатов. В каждой реализации делегата вычисляется текущая сумма или  нахится максимальное значение нескольких значений. Код с использованием делатов  выглядит  так:

static void DoRunningTotalAndMaximum() { List<int> 1st = new List<int> { 1, 2, 3, 4 };

_runningTotal = 0;

1st.Iterate(new ProcessValue(ProcessRunningTotal)); Console.WriteLine("Running total is (" + _runningTotal + ")");

_maxValue = int.MinValue;

1st.Iterate(new ProcessValue(ProcessMaximumValue)); Console.WriteLine("Maximum value is (" + _maxValue + ")");

}

В пример е метод  DoRunningTotalAndMaximum*) создает экземпляр класса 1st И присваивает ему значение, используя нотацию инициализатора объекта. Потом для обработки в цикле отдельных элементов вызывается метод 1st. iterate о  с  делатом для метода ProcessRunningTotal О. После вычисления и вывода на экран суммы значений,  находится  и  выводится  на экран  максимальное значение.

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

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

По теме:

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