foreach循环中的匿名委托

时间:2012-06-05 12:41:04

标签: c# delegates foreach scope anonymous-function

  

可能重复:
  Question about foreach and delegates

我想知道这里出现了什么现象:

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

1 个答案:

答案 0 :(得分:-2)

这是C#中一个已知的“bug”(我认为也是VB.NET)。简单的答案是你创建的localString变量是在foreach中的作用域,因此每个itteration都会使用它的一个新副本,但在另一种情况下,你只需引用s,它最终会成为c(在你打印之前)最小)。为了“解决”这类问题,我已经做了一个实践

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

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