我尝试在循环时删除一行时出现以下错误。
C#:收藏被修改;枚举操作可能无法执行
我已经做了一段时间的研究了,我在这里看过一些类似的帖子,但我还是找不到合适的答案。
foreach (DataTable table in JobsDS.Tables)
{
foreach (DataRow row in table.Rows)
{
if (row["IP"].ToString() != null && row["IP"].ToString() != "cancelled")
{
string newWebServiceUrl = "http://" + row["IP"].ToString() + "/mp/Service.asmx";
webService.Url = newWebServiceUrl;
string polledMessage = webService.mpMethod(row["IP"].ToString(), row["ID"].ToString());
if (polledMessage != null)
{
if (polledMessage == "stored")
{
removeJob(id);
}
}
}
}
}
任何帮助将不胜感激
答案 0 :(得分:14)
不使用foreach
,而是使用反向for
循环:
for(int i = table.Rows.Count - 1; i >= 0; i--)
{
DataRow row = table.Rows[i];
//do your stuff
}
删除行确实会修改原始的行集合。如果大多数枚举器在枚举过程中检测到源序列发生了变化,那么大多数枚举器都会被设计为爆炸 - 而不是试图处理foreach
所有变化的奇怪可能性,并且可能会引入非常微妙的错误,它更简单地禁止它更安全。
答案 1 :(得分:3)
您无法修改其周围foreach
内的集合。
相反,您应该使用向后for
循环。
答案 2 :(得分:3)
如果要从元素列表中的循环中删除元素,诀窍是使用for循环,从最后一个元素开始并转到第一个元素。
在你的例子中:
int t_size = table.Rows.Count -1;
for (int i = t_size; i >= 0; i--)
{
DataRow row = table.Rows[i];
// your code ...
}
编辑:不够快:))
答案 3 :(得分:0)
此外,如果您依赖处理行的顺序,并且反向循环不适合您。您可以将要删除的行添加到List中,然后在退出foreach循环后,可以删除添加到列表中的行。例如,
foreach (DataTable table in JobsDS.Tables)
{
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow row in table.Rows)
{
if (row["IP"].ToString() != null && row["IP"].ToString() != "cancelled")
{
string newWebServiceUrl = "http://" + row["IP"].ToString() + "/mp/Service.asmx";
webService.Url = newWebServiceUrl;
string polledMessage = webService.mpMethod(row["IP"].ToString(), row["ID"].ToString());
if (polledMessage != null)
{
if (polledMessage == "stored")
{
//removeJob(id);
rowsToRemove.Add(row);
}
}
}
}
rowsToRemove.ForEach(r => removeJob(r["ID"].ToString()));
}
答案 4 :(得分:0)
以某种方式removeJob(id)
更改了您枚举的IEnumebles之一(table.Rows
或JobsDS.Tables
,从方法的名称,我猜它将是后者),也许是通过DataBinding。
我不确定向后for
是否会直接起作用,因为它似乎是从内部foreach中删除外部foreach中枚举的元素。如果没有关于removeJob(id)中发生的事情的更多信息,很难说清楚。