3

重複の可能性:
foreach とデリゲートに関する質問

ここでどのような現象が起こっているのか知りたいです:

List<string>同じ文字列を返すデリゲートのリストに a を変換すると、うまくいきません。

これは、入力リストに対して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
4

1 に答える 1

-2

これはC#の既知の「バグ」です(VB.NETもそうだと思います)。簡単な答えは、作成したlocalString変数はforeach内でスコープされるため、その新しいコピーが各反復に使用されますが、それ以外の場合は単にsを参照するだけで、最終的にはcになります(少しでも)。この種の問題を「解決」するために、私はそれを実践しました

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

私がそのような代表者のために使うたびに。

于 2012-06-05T12:44:49.983 に答える