如何修改或删除可枚举集合中的项目,同时在C#中迭代

我必须从数据表中删除一些行。 我听说在迭代中更改集合是不正确的。 所以,而不是一个for循环中,我检查行是否符合删除的要求,然后将其标记为删除,我应该先遍历数据表,并添加列表中的所有行,然后遍历列表和标记删除的行。 这是什么原因,我有什么替代品(而不是使用行列表我的意思)?

如果使用简单的for循环,则可以从集合中删除元素。

看看这个例子:

  var l = new List<int>(); l.Add(0); l.Add(1); l.Add(2); l.Add(3); l.Add(4); l.Add(5); l.Add(6); for (int i = 0; i < l.Count; i++) { if (l[i] % 2 == 0) { l.RemoveAt(i); i--; } } foreach (var i in l) { Console.WriteLine(i); } 

通过列表向后迭代听起来像是一个更好的方法,因为如果你删除一个元素,其他元素“陷入缺口”,这并不重要,因为你已经看过这些。 此外,你不必担心你的计数器variables变得比.Count大。

  List<int> test = new List<int>(); test.Add(1); test.Add(2); test.Add(3); test.Add(4); test.Add(5); test.Add(6); test.Add(7); test.Add(8); for (int i = test.Count-1; i > -1; i--) { if(someCondition){ test.RemoveAt(i); } } 

以@bruno代码,我会做倒退。

因为当你向后移动时,缺失的数组索引不会影响循环的顺序。

 var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 }); for (int i = l.Count - 1; i >= 0; i--) if (l[i] % 2 == 0) l.RemoveAt(i); foreach (var i in l) { Console.WriteLine(i); } 

但是,现在,我会使用LINQ:

 var l = new List<int>(new int[] { 0, 1, 2, 3, 4, 5, 6 }); l.RemoveAll(n => n % 2 == 0); 

由于您正在使用DataTable,并且需要能够使用表格适配器将任何更改保留回服务器(请参阅注释),下面是如何删除行的示例:

 DataTable dt; // remove all rows where the last name starts with "B" foreach (DataRow row in dt.Rows) { if (row["LASTNAME"].ToString().StartsWith("B")) { // mark the row for deletion: row.Delete(); } } 

在行上调用delete会将其RowState属性更改为Deleted,但将已删除的行留在表中。 如果仍然需要在保留更改回服务器之前使用此表(例如,如果要显示表的内容减去删除的行),则需要检查每行的RowState,如同迭代它一样:

 foreach (DataRow row in dt.Rows) { if (row.RowState != DataRowState.Deleted) { // this row has not been deleted - go ahead and show it } } 

从集合中删除行(如在布鲁诺的答案中)将打破表适配器,并且通常不应该用DataTable来完成。

while循环会处理这个问题:

 int i = 0; while(i < list.Count) { if(<codition for removing element met>) { list.RemoveAt(i); } else { i++; } } 

如果您使用委托而不是lambdaexpression式来定位.NET 2.0(无LINQ / lambdaexpression式),也可以使用chakrit的解决scheme:

 public bool IsMatch(int item) { return (item % 3 == 1); // put whatever condition you want here } public void RemoveMatching() { List<int> x = new List<int>(); x.RemoveAll(new Predicate<int>(IsMatch)); } 

删除或添加到列表,而迭代通过它可以打破它,就像你说的。

我经常用两个列表来解决问题:

 ArrayList matches = new ArrayList(); //second list for MyObject obj in my_list { if (obj.property == value_i_care_about) matches.addLast(obj); } //now modify for MyObject m in matches { my_list.remove(m); //use second list to delete from first list } //finished. 

当我需要从列举的集合中删除一个项目时,我通常会将其枚举为相反的列表。