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