C# 安全删除 ForEach 中的 DataRow

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2341580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:36:15  来源:igfitidea点击:

Safely Removing DataRow In ForEach

c#ado.netdatatablecollectionsdatarow

提问by Hyman Kada

I don't understand why this code does not work.

我不明白为什么这段代码不起作用。

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

采纳答案by Jon Skeet

Even though DataRow.Deletedoesn't modify the state of the collection, Microsoft documentationstates that you shouldn't call it while iterating over the collection:

即使DataRow.Delete不修改集合的状态,Microsoft 文档也指出您不应在迭代集合时调用它:

Neither Delete nor Remove should be called in a foreach loop while iterating through a DataRowCollection object. Delete nor Remove modify the state of the collection.

在遍历 DataRowCollection 对象时,不应在 foreach 循环中调用 Delete 和 Remove。Delete 或 Remove 修改集合的状态。

The best solution is usually to create a separate collection (e.g. a List<DataRow>) of items you want to remove, and then remove them afteryou've finished iterating.

最好的解决方案通常是创建一个单独的集合(例如 a List<DataRow>)要删除的项目,然后在完成迭代删除它们。

This is also the solution for situations where you want to remove items from a collection, as most collections in .NET don't allow you to change the contents of the collection while you're iterating over it.

这也是您想要从集合中删除项目的情况的解决方案,因为 .NET 中的大多数集合不允许您在迭代集合时更改集合的内容。

回答by Lucero

The Rowscontent changes while you are iterating if you delete one row, which renders the iteration invalid.

Rows内容的变化,而如果删除一行,这使得迭代无效你迭代。

You can, however, copy the rows into a collection first and then iterate over the collection and delete the rows that way. This makes sure that the iteration is not interrupted by changing data to be iterated.

但是,您可以先将行复制到集合中,然后遍历集合并以这种方式删除行。这确保迭代不会因更改要迭代的数据而中断。

回答by DOK

This applies to pretty much any collection. If you try to delete an item while looping through the collection, you will have a problem. For example, if you delete row #3, then the previous row #4 becomes row #3.

这几乎适用于任何集合。如果您在遍历集合时尝试删除项目,则会出现问题。例如,如果您删除第 #3 行,则前一行 #4 将成为第 #3 行。

回答by Thibault Falise

You cannot modify a collection while you're iterating on it using a foreachstatement.

在使用foreach语句对其进行迭代时,您不能修改集合。

you can try something like that :

你可以尝试这样的事情:

List<DataRow> deletedRows = new List<DataRow>();

foreach (DataRow dataRow in dataTable.Rows)
{
    if(true) deletedRows.Add(dataRow);
}

foreach(DataRow dataRow in deletedRows)
{
    dataRow.Delete();
}

回答by Thibault Falise

Use this:

用这个:

for (int i = 0; i < myDataTable.Rows.Count; i++)

{

 myDataTable[i].Delete();

}

回答by VMAtm

Safest way - use forloop

最安全的方法 - 使用for循环

for (int i = datatable.Rows.Count - 1; i >= 0; i--) 
{
    if (true)
    {
        datatable.Rows[i].Delete();
    }
}

Don't forget to AcceptChangesto remove all marked rows:

不要忘记AcceptChanges删除所有标记的行:

datatable.AcceptChanges();

回答by IAbstract

Where items have a Count, this is what I have done:

项目有一个Count,这就是我所做的:

int Count = myTable.Rows.Count;

while (Count > 0) // replace condition with myTable.Rows.Count if unconditionally performed on all rows
{
    DataRow row = myTable.Rows[0] // or however you want to find your index

    // do some work
    myTable.Rows.Remove(row);

    // if you want to perform a check to break out of while
    if (someCondition)
        Count = 0;
    else
        Count = myTable.Rows.Count;
}

Note, that where objects have a .GetXXXX()collection, like FileInfo(IIRC), deleting item contents in a foreachis acceptable. One solution I have considered is creating an extension method that provides a .GetItems()method.

请注意,在对象具有.GetXXXX()集合的情况下,例如FileInfo(IIRC),删除 a 中的项目内容foreach是可以接受的。我考虑过的一个解决方案是创建一个提供.GetItems()方法的扩展方法。

回答by Chris

If you call the delete method you just have to call AcceptChanges()on the table you are modifying, after the foreach loop.

如果您调用 delete 方法,您只需AcceptChanges()在 foreach 循环之后调用您正在修改的表。

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

dataTable.AcceptChanges();

The delete method simply marks the row for deletion.

delete 方法只是标记要删除的行。

http://msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx

http://msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx

回答by neverlandx

may be my answer not longer useful. exception throw in Foreach with DataRow only appear in .Net 2.0 and earlier, the reason is description at msdn http://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx

可能是我的答案不再有用。Foreach with DataRow 中的异常抛出仅出现在 .Net 2.0 及更早版本中,原因是 msdn http://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80 ).aspx

If the RowState of the row is Added, the row is removed from the table.

如果行的 RowState 为已添加,则从表中删除该行。

The RowState becomes Deleted after you use the Delete method. It remains Deleted until you call AcceptChanges.

使用 Delete 方法后,RowState 变为 Deleted。在您调用 AcceptChanges 之前,它会保持 Deleted 状态。

A deleted row can be undeleted by invoking RejectChanges.

可以通过调用 RejectChanges 来取消删除已删除的行。

to pass this problem you can call DataTable.AcceptChanges() before using foreach

要传递此问题,您可以在使用 foreach 之前调用 DataTable.AcceptChanges()

回答by Mark Macneil Bikeio

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

dataTable.AcceptChanges();

Please Refer the snaps to understatnd the working of it.

请参考快照以了解它的工作原理。

  1. Just Deleted but not removed from the DataTable.
  1. 刚刚删除但未从数据表中删除。

enter image description here

在此处输入图片说明

  1. Break point before AcceptChanges() Function. enter image description here
  2. After Eexecuting AcceptChanges() Function. enter image description here
  1. AcceptChanges() 函数之前的断点。 在此处输入图片说明
  2. 在执行 AcceptChanges() 函数之后。 在此处输入图片说明

I Hope this issue resolved now.

我希望这个问题现在解决了。