foreach 循环中的匿名委托

本文关键字:循环 foreach | 更新日期: 2023-09-27 18:36:15

可能的重复项:
关于每个和代表

的问题

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

List<string>转换为返回相同字符串的委托列表会出错。

当我直接使用输入列表上的foreach返回的变量时,这种情况WrongConversion发生。 (每次返回列表中的最后一个字符串

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

foreach 循环中的匿名委托

这是

C# 中一个已知的"错误"(我认为也是 VB.NET 错误)。简单的答案是,您创建的localString变量的作用域在foreach内,因此每次迭代都使用它的新副本,但是在另一种情况下,您只需引用s,最终最终会得到c(至少在打印之前)。为了"解决"此类问题,我已经把它作为一种实践

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

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