2013-02-25 69 views
0

以下是示例代碼。在Visual Studio 2010和2012中找到不同的答案

var values = new List<string>() { "Stack", "Over", "Go" }; 

var funcs = new List<Func<string>>(); 

foreach(var v in values) 

    funcs.Add(()=>v); 
foreach(var f in funcs) 

    Console.WriteLine(f()); 

當我運行這段代碼與Visual Studio 2010中我得到的輸出: Go Go Go

但是,當我試圖在Visual Studio 2012的同一代碼的輸出是: Stack Over Go

爲什麼它的行爲有什麼不同?

+5

您可以確保您提供的代碼與您輸出的聲明相符。上面的代碼似乎不太可能產生「愚蠢愚蠢」或「鮑勃愚蠢」 – 2013-02-25 11:33:32

+0

**什麼?**甚至可能輸出這種代碼可能「愚蠢愚蠢愚蠢」或「鮑勃愚蠢」 ? – 2013-02-25 11:33:47

+2

我懷疑它會生成'Go Go Go'和'Stack Over Go',但發佈生成你提到的輸出的代碼。 – LukeHennerley 2013-02-25 11:34:18

回答

10

原因是編譯器被更改爲創建閉包中捕獲的變量的臨時副本。

採取下面的代碼在VS 2012:

foreach(var v in values) 
    funcs.Add(() => v); 

的VS 2012編譯器從該生成的代碼是等效於由VS 2010編譯該代碼生成的代碼:

foreach(var v in values) 
{ 
    var tmp = v; 
    funcs.Add(() => tmp); 
} 

的這種變化的原因是許多開發人員發現VS 2010編譯器的行爲出乎意料。

+1

+1。另請參閱:Eric Lippert關於此主題的博客文章: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop -variable-considered-harmful.aspx – Ergwun 2013-02-25 11:36:12

+0

很高興停止在任何地方製作變量的循環副本 - 總是覺得自己總是這麼笨 - – 2013-02-25 11:36:46

+0

@Ergwun:謝謝 - 我只是在尋找那個鏈接來添加一些官方的東西 – 2013-02-25 11:38:19

相關問題