Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#循环:遍历数组_C#_Loops - Fatal编程技术网

C#循环:遍历数组

C#循环:遍历数组,c#,loops,C#,Loops,如果我有如下循环: foreach (string pass in new string[] { "pass1", "pass2", "pass3" }) { x = pass; //etc } 匿名字符串数组最初是创建一次,还是每次传递都重新创建一次 我相信前者,但同事们确信这是一个等待发生的错误,因为他们说foreach循环的每次迭代都会产生一个新的字符串数组 VS反汇编代码表明我是对的,但我想确定一下 我们研究这个问题的原因是试图了解一个神秘的bug,该bug报告在对集合进行迭代时集合

如果我有如下循环:

foreach (string pass in new string[] { "pass1", "pass2", "pass3" })
{
 x = pass; //etc
}
匿名字符串数组最初是创建一次,还是每次传递都重新创建一次

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

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


我们研究这个问题的原因是试图了解一个神秘的bug,该bug报告在对集合进行迭代时集合已被更改。

您可以对其进行测试(有很多方法可以这样做,但这是一个选项):

然后看看结果如何

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

根据和,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();
   }
}
{
IEnumerator e=((IEnumerable)新字符串[]{“pass1”、“pass2”、“pass3”});
尝试
{ 
字符串传递;//在实际循环之外
while(如MoveNext())
{
pass=(字符串)e.Current;
x=通过;
}
}
最后
{ 
如果(e!=null)((IDisposable)e.Dispose();
}
}
如您所见,枚举器是在循环之前创建的

@罗琳正确地指出,编译器对数组的处理略有不同。Foreach循环优化为带有数组的for循环。根据您的代码,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;
}
string[]临时数组;
字符串[]数组=新字符串[]{“pass1”、“pass2”、“pass3”};
tempArray=数组;
用于(字符串计数器=0;计数器

初始化也只发生一次。

初始化最初只创建一次

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


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

string[] array = new string[]
{
    "pass1",
    "pass2",
    "pass3"
};
for (int i = 0; i < array.Length; i++)
{
    string pass = array[i];
}
string[]数组=新字符串[]
{
“通行证1”,
“通行证2”,
“通行证3”
};
for(int i=0;i
因此,是的,数组只创建一次


然而,说服同事的最佳参考可能是C#规范的第8.8.4节,该节将告诉您LazyBerezovsky的答案的基本功能。

下面的示例应该回答是否重新创建阵列的问题

        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!");
        }

您可以很容易地对其进行测试,例如,输入
DateTime
值,而不是字符串,并在每次迭代中检查成员。另一种方法是在调试模式下逐步检查代码,以显示其只计算一次。创建字符串数组的代码将只突出显示一次。或者
新字符串[]{“pass1”,“pass”+i++,“pass3”}
“一个神秘的错误,报告在迭代集合时已更改”-为什么不将其作为问题发布?“一个神秘的bug,报告在对集合进行迭代时集合已被更改。“-这表明您的代码正在从循环内的集合中删除项。这就是你应该从C#5.0开始寻找+1的地方,变量
pass
将在循环中。我认为这对于数组来说有细微的不同。。。它不是把一个
foreach
循环变成了
for
循环吗?@老实说,你的第一个代码块是最好的答案,因为它是规范所说的(8.8.4)-数组的
for
循环只是一点优化。我尽了最大努力:)(不总是成功的…)谢谢-问题已回答。+1并感谢您指出针对数组的不同foreach编译!谢谢-问题已回答。这是一个很好的方法来确保:)我建议使用
new[]{DateTime.Now,DateTime.Now,DateTime.Now}
使代码看起来更短:)
string[] array = new string[]
{
    "pass1",
    "pass2",
    "pass3"
};
for (int i = 0; i < array.Length; i++)
{
    string pass = array[i];
}
        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!");
        }