2016-12-28 55 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()的范围。从C#5指定部7.15.5.1:

当外变量由匿名函数引用,外部变量被说已经捕获由匿名函数。通常,局部变量的生存期限于执行与其关联的块或语句(第5.1.7节)。但是,捕获的外部变量的生命周期至少会延长,直到从匿名函数创建的委托或表达式树变为符合垃圾回收的条件。

+0

谢谢!但是,我是否理解7.15.5.1正确?:''结果'至少在'del1'的范围将被关闭之前保证活着? – user1234567

+1

@ user1234567:否,直到委托人可以进行垃圾回收。 'del1'是一个局部变量,恰好有一个对委托的引用。您可以将值传递给其他保留对同一个委托的引用并使其保持活动状态的其他值。基本上,委托具有它所需的所有状态,包括'result'变量。你需要考虑*对象*和垃圾收集,而不是变量和范围。 –

相关问题