2016-12-28 48 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'變量。你需要考慮*對象*和垃圾收集,而不是變量和範圍。 –

相關問題