c#循环:遍历数组

本文关键字:数组 遍历 循环 | 更新日期: 2023-09-27 18:01:36

如果我有一个像下面这样的循环:

foreach (string pass in new string[] { "pass1", "pass2", "pass3" })
{
 x = pass; //etc
}

匿名字符串数组最初创建一次,还是为每次传递重新创建一次?

我相信是前者,但同事们认为这是一个等待发生的错误,因为他们说foreach循环的每次迭代都会创建一个新的字符串数组。

VS反汇编代码表明我是对的,但我想确定。

我们看这个的原因是试图理解一个神秘的错误,报告一个集合在迭代它时被改变了

c#循环:遍历数组

根据Eric Lippert的博客和规范,foreach循环是一个语法糖:

{
  IEnumerator<string> e = ((IEnumerable<string>)new string[] { "pass1", "pass2", "pass3" }).GetEnumerator();
   try
   { 
     string pass; // OUTSIDE THE ACTUAL LOOP
      while(e.MoveNext())
      {
        pass = (string)e.Current;
        x = pass;
      }
   }
   finally
   { 
      if (e != null) ((IDisposable)e).Dispose();
   }
}

可以看到,枚举数在循环之前创建。

@Rawling正确指出,编译器对数组的处理略有不同。对于带有数组的循环,Foreach循环被优化为。根据c# foreach的内部原理,你的c# 5代码看起来像:

string[] tempArray;
string[] array = new string[] { "pass1", "pass2", "pass3" };
tempArray = array;
for (string counter = 0; counter < tempArray.Length; counter++)
{
    string pass = tempArray[counter];
    x = pass;
}

初始化也只发生一次

如果您查看ILSpy,该代码将被翻译成类似

的内容。
string[] array = new string[]
{
    "pass1",
    "pass2",
    "pass3"
};
for (int i = 0; i < array.Length; i++)
{
    string pass = array[i];
}

所以是的,数组只创建一次。

然而,说服你的同事的最好参考可能是c#规范的8.8.4节,它将告诉你LazyBerezovsky的答案是什么。

最初只创建一次。

我尝试了Ofer Zelig(来自评论)的建议

foreach (DateTime pass in new DateTime[] { DateTime.Now, DateTime.Now, DateTime.Now })
{
    int x = pass.Second; //etc
}

并放置一个断点。它将为所有3次迭代提供相同的秒数,即使您在迭代之间等待。

您可以测试它(有很多方法可以这样做,但这是一种选择):

string pass4 = "pass4";
foreach (string pass in new string[] { "pass1", "pass2", "pass3", pass4 })
{
    pass4="pass5 - oops";
    x = pass; //etc
}

然后看看结果是什么

你会发现你是对的——它只执行一次。

下面的示例应该回答是否重新创建数组的问题。

        int i = 0;
        int last = 0;
        foreach (int pass in new int[] { i++, i++, i++, i++, i++, i++, i++ })
        {
            if (pass != last)
            {
                throw new Exception("Array is reintialized!");
            }
            last++;
        }
        if (i > 7)
        {
            throw new Exception("Array is reintialized!");
        }