C# 修改循环内的元素会弄乱for循环
我使用以下C# 修改循环内的元素会弄乱for循环,c#,ienumerable,C#,Ienumerable,我使用以下for循环来迭代IEnumerable: for(int i=0;iTranslator.Translate(obj.EnglishText,“English”,File.Lang)); 进度报告(i+1); 等待任务。延迟(延迟); } 上面的代码正在跳过备用元素。即使计数为7,循环也只运行了4次 我试图用等效的foreach循环替换for循环: int电流=0; foreach(项目中的var项目) { if(cancellationToken.IsCancellationReq
for
循环来迭代IEnumerable:
for(int i=0;iTranslator.Translate(obj.EnglishText,“English”,File.Lang));
进度报告(i+1);
等待任务。延迟(延迟);
}
上面的代码正在跳过备用元素。即使计数为7,循环也只运行了4次
我试图用等效的foreach
循环替换for
循环:
int电流=0;
foreach(项目中的var项目)
{
if(cancellationToken.IsCancellationRequested)
{
返回;
}
item.TranslatedText=wait Task.Run(()=>Translator.Translate(item.EnglishText,“English”,File.Lang));
进度报告(++当前);
等待任务。延迟(延迟);
}
它工作得很好,我不知道这两者有什么不同
我又挖了一点,发现如果我把绳子移开
obj.TranslatedText=wait Task.Run(()=>Translator.Translate(obj.EnglishText,“English”,File.Lang))代码>
从第一个例子来看,它执行得很好
不允许我修改IEnumerable的内容吗?只是好奇
更新1
我在下面贴了一个可复制的例子
现在我们有了一个完整的示例,我们可以看到问题所在。您用于项的集合是一个依赖于TranslatedText
的查询:
var source=collection.Where(x=>string.IsNullOrEmpty(x.TranslatedText));
对于您正在处理的项目,您对obj
执行的操作将使该查询的结果无效:
obj.TranslatedText=“某物”;
因此,在for
循环中,最初所有10个Translation
对象都满足条件,因此Count()
为10。在循环的第一次迭代中,访问第一个元素(元素0),并将obj.TranslatedText
设置为“something”
现在,在循环的每个迭代中,您都在计算“查询的当前结果”——现在是9。然后在查询的当前结果中按索引访问元素-因此当i
为1时,将跳过查询的第一个匹配项并访问第二个匹配项。但这并不是原始集合中的第二个匹配项,而是当前查询的第二个匹配项,它已经跳过了第一个元素,因为您修改了该元素以设置转换。因此,原始元素索引1在循环的第二次迭代中被跳过,而您将为原始元素索引2设置翻译文本。然后Count()
变为8,以此类推
使用foreach
循环,您只需在查询上迭代一次,而当您仍然使“正在查看的当前元素”的查询条件无效时,查询处理无论如何都不需要再次检查
因此,要么使用foreach
循环,要么如果希望通过索引访问元素,那么应该首先具体化查询。例如,您可以使用:
//对查询求值一次,将结果存储在列表中
var list=items.ToList();
//现在,您可以对列表进行操作,而不用担心查询
//正在重新评估。
for(int i=0;iTranslator.Translate(obj.EnglishText,“English”,File.Lang));
进度报告(i+1);
等待任务。延迟(延迟);
}
现在我们有了一个完整的示例,我们可以看到问题所在。您用于项的集合是一个依赖于TranslatedText
的查询:
var source=collection.Where(x=>string.IsNullOrEmpty(x.TranslatedText));
对于您正在处理的项目,您对obj
执行的操作将使该查询的结果无效:
obj.TranslatedText=“某物”;
因此,在for
循环中,最初所有10个Translation
对象都满足条件,因此Count()
为10。在循环的第一次迭代中,访问第一个元素(元素0),并将obj.TranslatedText
设置为“something”
现在,在循环的每个迭代中,您都在计算“查询的当前结果”——现在是9。然后在查询的当前结果中按索引访问元素-因此当i
为1时,将跳过查询的第一个匹配项并访问第二个匹配项。但这并不是原始集合中的第二个匹配项,而是当前查询的第二个匹配项,它已经跳过了第一个元素,因为您修改了该元素以设置转换。因此,原始元素索引1在循环的第二次迭代中被跳过,而您将为原始元素索引2设置翻译文本。然后Count()
变为8,以此类推
使用foreach
循环,您只需在查询上迭代一次,而当您仍然使“正在查看的当前元素”的查询条件无效时,查询处理无论如何都不需要再次检查
因此,要么使用foreach
循环,要么如果希望通过索引访问元素,那么应该首先具体化查询。例如,您可以使用:
//对查询求值一次,将结果存储在列表中
var list=items.ToList();
//现在,您可以对列表进行操作,而不用担心查询
//正在重新评估。
for(int i=0;i