Добавить в цитаты Настройки чтения

Страница 227 из 502

<b>      }</b>

<b>      return sum; // возвратить значение из анонимного метода</b>

<b>    };</b>

<b>    result = count(3);</b>

<b>    Console.WriteLine(&quot;Сумма 3 равна &quot; + result);</b>

<b>    Console.WriteLine();</b>

<b>    result = count (5);</b>

<b>    Console.WriteLine(&quot;Сумма 5 равна &quot; + result);</b>

<b>  }</b>

<b>}</b>

В этом варианте кода суммарное значение возвращается кодовым блоком, связанным с экземпляром делегата count. Обратите внимание на то, что оператор return применяется в анонимном методе таким же образом, как и в именованном методе. Ниже приведен результат выполнения данного кода.

<b>0</b>

<b>1</b>

<b>2</b>

<b>3</b>

<b>Сумма 3 равна 6</b>

<b>0</b>

<b>1</b>

<b>2</b>

<b>3</b>

<b>4</b>

<b>5</b>

<b>Сумма 5 равна 15</b>

Локальная переменная, в область действия которой входит анонимный метод, называется внешней переменной. Такие переменные доступны для использования в анонимном методе. И в этом случае внешняя переменная считается захваченной. Захваченная переменная существует до тех пор, пока захвативший ее делегат не будет собран в "мусор". Поэтому если локальная переменная, которая обычно прекращает свое существование после выхода из кодового блока, используется в анонимном методе, то она продолжает существовать до тех пор, пока не будет уничтожен делегат, ссылающийся на этот метод.

Захват локальной переменной может привести к неожиданным результатам. В качестве примера рассмотрим еще один вариант программы подсчета с суммированием чисел. В данном варианте объект CountIt конструируется и возвращается статическим методом Counter(). Этот объект использует переменную sum, объявленную в охватывающей области действия метода Counter(), а не самого анонимного метода. Поэтому переменная sum захватывается анонимным методом. Метод Counter() вызывается в методе Main() для получения объекта CountIt, а следовательно, переменная sum не уничтожается до самого конца программы.

<b>// Продемонстрировать применение захваченной переменной,</b>

<b>using System;</b>

<b>// Этот делегат возвращает значение типа int</b>

<b>// и принимает аргумент типа int. </b>

<b>delegate int CountIt(int end);</b>

<b>class VarCapture {</b>

<b>  static CountIt Counter() {</b>

<b>    int sum = 0;</b>

<b>    // Здесь подсчитанная сумма сохраняется в переменной sum.</b>

<b>    CountIt ctObj = delegate (int end) {</b>

<b>      for(int i=0; i &lt;= end; i++) {</b>

<b>        Console.WriteLine(i);</b>

<b>        sum += i;</b>

<b>      }</b>

<b>      return sum;</b>

<b>    };</b>

<b>    return ctObj;</b>

<b>  }</b>

<b>  static void Main() {</b>

<b>    // Получить результат подсчета.</b>

<b>    CountIt count = Counter();</b>

<b>    int result;</b>

<b>    result = count(3);</b>

<b>    Console.WriteLine(&quot;Сумма 3 равна &quot; + result);</b>

<b>    Console.WriteLine();</b>

<b>    result = count(5);</b>

<b>    Console.WriteLine(&quot;Сумма 5 равна &quot; + result);</b>

<b>  }</b>

<b>}</b>

Ниже приведен результат выполнения этой программы. Обратите особое внимание на суммарное значение.

<b>0</b>

<b>1</b>

<b>2</b>

<b>3</b>

<b>Сумма 3 равна 6</b>

<b>0</b>

<b>1</b>

<b>2</b>

<b>3</b>

<b>4</b>

<b>5</b>

<b>Сумма 5 равна 21</b>

Как видите, подсчет по-прежнему выполняется как обычно. Но обратите внимание на то, что сумма 5 теперь равна 21, а не 15! Дело в том, что переменная sum захватывается объектом ctObj при его создании в методе Counter(). Это означает, что она продолжает существовать вплоть до уничтожения делегата count при "сборке мусора" в самом конце программы. Следовательно, ее значение не уничтожается после возврата из метода Counter() или при каждом вызове анонимного метода, когда происходит обращение к делегату count в методе Main().