2013-02-27 165 views
1

我真的不知道为什么for循环只循环一次。我认为逻辑是正确的,下面是代码。C#为什么List.Remove()打破'for循环'?

// the list is named 'dataList' 

for(int i = 0 ; i < dataList.Count; i ++) 
{ 
    string[] data = dataList[i].Split('+'); 
    string[] wsno = data[0].Split(':'); 
    if(wsno[1].Equals(tbWorkSheet.Text)) 
    { 
     dataList.Remove(dataList[i]) <<<< remove string that has the same number 
     //data removed 
     //for loop ends up here idk why.. 
    } 
} 

dataList.Count将是列表的大小。

这种情况是这样的.. 我想删除存储在列表中的多个字符串,每个字符串都有它的组号。 因此,for循环将循环直到最后一个。但是当它找到一个与所需数字相同的字符串时,它将执行将其删除的if语句。

+0

'dataList.Count'是什么样的价值特别? – Arran 2013-02-27 14:44:16

+0

你期待它循环多少次?它抛出异常吗? – 2013-02-27 14:44:18

+0

这通常是为什么在删除(即从count-1到0)时反向迭代的原因......它使索引管理变得更容易。 – spender 2013-02-27 14:47:34

回答

6

这是非常糟糕的主意。通过从列表中删除值,您将跳过列表中的下一个项目。

例如您的列表中有3项在索引0,1,2

第一次迭代中:i = 0 您在索引中删除0项列表现在有索引0项,1(拳头项目删除)。

第二次迭代:i = 1. 注意位于索引1处的项目是如何移动到0的。而我们的索引计数器从0变为1.所以我们将“跳过”这个项目。

如果您的列表中只有2个项目,他将在第一次删除后中断。这是因为您的指数增加时计数减少。

通过逆向排序,您将消除此问题。

List<int> list = new List<int> { 2, 1 }; 
for (int i = list.Count - 1; i >= 0; i--) 
{ 
    list.RemoveAt(i); 
} 

编辑:Rawling提到,您可以前进,如果你减少您柜台当您删除的项目。

for (int i = 0; i < list.Count; i++) 
{ 
    list.RemoveAt(i--); 
} 
+1

这是执行它的规范方式。 – 2013-02-27 14:48:17

+0

当我删除某些东西时,我会考虑前进和递减'i',但是也许只有在向前翻阅列表时很重要。 – Rawling 2013-02-27 14:49:44

+0

哇谢谢你。这工作.. – 2013-02-27 14:55:20

-5

您不能在for循环中更改列表。 您可以将要删除的数据保存在另一个列表中,然后在退出循环后将其删除。

+1

你可以。你不能在foreach循环中。 – Corak 2013-02-27 14:45:28

0

删除项目后,您忘记了递减i。这会跳过下一个项目,因为所有后续项目将被重新编号减1。

0

循环向后通过列表:

for(int i = dataList.Count; i >= 0 ; i--) 
{ 
    string[] data = dataList[i].Split('+'); 
    string[] wsno = data[0].Split(':'); 
    if(wsno[1].Equals(tbWorkSheet.Text)) 
    { 
     dataList.RemoveAt(dataList[i]) <<<< remove string that has the same number 
     //data removed 
     //for loop ends up here idk why.. 
    } 
} 
+1

如果列表中有重复的条目,这可能仍然会导致问题 - “Remove”可能不会删除第i个元素。 'RemoveAt'会更好。 – Rawling 2013-02-27 14:47:41

0

我宁愿做一个新的列表,而不是修改原始集合。

能整齐地使用LINQ来完成:

dataList = 
    dataList 
     .Select(x => new{ 
      dataItem = x, 
      secondWsno = x.Split('+').First().Split(':').Skip(1).First() 
     }) 
     .Where(x => !x.secondWsno.Equals(tbWorkSheet.Text)) 
     .ToList(); 
+0

那么如果你有一个包含很多项目的列表,而你只是删除一个或两个,那么重新创建列表只是为了删除一小部分项目,这是相当过分的。当你删除一个重要的百分比时,这通常会更好。 – Servy 2013-02-27 14:57:49

+0

很容易高估这些操作的成本。我宁愿这样做,直到我看到它是有问题的,但是,是的,如果轻微移除它可能是矫枉过正。 – spender 2013-02-27 15:02:50