2016-12-28 2 views
0

Я новичок в C#. Я сталкивался с такой код-пример:Повторное использование сохранившейся локальной переменной в каждом вызове. UB?

namespace App1 
{ 
    delegate int Sum(int number); 

    class TestAnonymusMethod 
    { 
     static Sum m() 
     { 
      int result = 0; // is not zeroed between calls 

      Sum del = delegate (int number) 
      { 
       for (int i = 0; i <= number; i++) 
        result += i; 
       return result; 
      }; 
      return del; 
     } 

     static void Main() 
     { 
      Sum del1 = m(); 

      for (int i = 1; i <= 5; i++) 
       Console.WriteLine("Sum of {0} == {1}", i, del1(i)); 

      Console.ReadKey(); 
     } 
    } 
} 

результат:

Sum of 1 == 1 
Sum of 2 == 4 
Sum of 3 == 10 
Sum of 4 == 20 
Sum of 5 == 35 

Как вы видите, локальная переменная result не обнулить между вызовами. Это «неопределенное поведение»? Похоже, что это происходит из-за закрытия рамки result, срок ее жизни не определен.

Но каковы правила повторного использования живых существ в C#? Является ли это правилом - «повторно использовать всегда», или есть некоторые случаи, когда новый будет создан вместо повторного использования сохранившегося старого?

+2

Почему это должно быть обнулено? Вы вызываете метод «m()» только один раз, поэтому он инициализируется 0 только один раз. – Evk

+0

@Evk, я переименовал вопрос. Поскольку 'result' не является' static', для меня это выглядит немного странно (после C++) - повторное использование той же переменной (с ее текущим значением) в каждом вызове. – user1234567

ответ

3

Действительно ли это «неопределенное поведение»?

Нет, это четко определенное поведение - просто не то поведение, которое вы ожидаете.

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

Срок доставки result не распространяется на рамки m(). Из спецификации раздела 7.15.5.1 C# 5:

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

+0

Спасибо! Но понял ли я 7.15.5.1 правильно: «результат» будет гарантированно жив, по крайней мере, до тех пор, пока объем 'del1' не будет закрыт? – user1234567

+1

@ user1234567: Нет, пока делегат не станет элегантным для сбора мусора. 'del1' - это локальная переменная, которая просто имеет ссылку на делегата. Вы можете передать значение чему-то другому, которое сохраняет ссылку на одного и того же делегата и поддерживает его. В принципе, у делегата есть все необходимое состояние, в том числе переменная 'result'. Вы должны думать в терминах * объектов * и сбор мусора, а не переменных и объема. –