2012-06-05 51 views
3

可能重复:
Question about foreach and delegates匿名委托在foreach循环

我想知道是什么现象是怎么回事:

转换一个List<string>到列表代表返回相同的字符串出错。

这发生在WrongConversion当我直接工作在foreach通过输入列表返回的变量。 (列表中的最后一个字符串是每次返回的

CorrectConversion中,我首先分配一个局部变量并在委托中使用它。

这项任务起初似乎是多余的。

输入:

using System.Collections.Generic; 
class Program 
{ 
    delegate string StringReturner(); 

    static void Main(string[] args) 
    { 
    var list = new List<string> { "a", "b", "c" }; 
    Display(WrongConversion(list)); 
    Display(CorrectConversion(list)); 
    System.Console.ReadKey(); 
    } 
    static List<StringReturner> WrongConversion(List<string> list) 
    { 
    var result = new List<StringReturner>(); 
    foreach (var s in list) 
    { 
     result.Add(() => { return s; }); // <========= s is always "c" ? 
    } 
    return result; 
    } 
    static List<StringReturner> CorrectConversion(List<string> list) 
    { 
    var result = new List<StringReturner>(); 
    foreach (var s in list) 
    { 
     var localString = s;    // <========= What happens here? 
     result.Add(() => { return localString; }); 
    } 
    return result; 
    } 
    private static void Display(List<StringReturner> list) 
    { 
    foreach (var stringReturner in list) 
     System.Console.Write(stringReturner()); 
    System.Console.WriteLine(); 
    } 
} 

输出:

ccc 
abc 
+0

这是一百万个问题的重复。它与关闭局部变量有关。 – jason

回答

-2

这是在C#中已知的 “臭虫”(VB.NET太,我认为)。简单的答案是你创建的localString变量是在foreach内部的范围内的,因此它的一个新副本用于每个迭代,但是在另一种情况下,你只需引用s,最终以c结尾(在打印之前最小)。为了“解决”这类问题,我做了一个练习

foreach(var _s = ....) { 
    var s = _s; 
    /* code here that uses s */ 
} 

每次我有这样的代表使用。

+1

这也是StackOverflow社区的一个已知问题。因此,重复一样。 – jason