[RESOLVED] [2005] Collection was modified; enumeration operation might not execute.
Hi,
I'm iterating through a DataTable, and perfoming some logic to determine whether I should delete certain rows from the table. I keep on getting the error, "Collection was modified; enumeration operation might not execute", but I don't know how to handle it.
I've hacked about with this a bit, and can't get it to work.
Code:
Dim row As DataRow
intLoop = 0
For Each row In dsCopyOfDataView.Tables("tblExchangeRates").Rows
strCurrentSearchString = dsCopyOfDataView.Tables("tblExchangeRates").Rows(intLoop)(5)
MsgBox(dsCopyOfDataView.Tables(0).Rows.IndexOf(row).ToString)
If strPreviousSearchString = strCurrentSearchString Then
strPreviousSearchString = strCurrentSearchString
dsCopyOfDataView.Tables("tblExchangeRates").Rows.RemoveAt(intLoop)
End If
strPreviousSearchString = strCurrentSearchString
intLoop = dsCopyOfDataView.Tables(0).Rows.IndexOf(row) + 1
Next
The thinking behind:
Code:
intLoop = dsCopyOfDataView.Tables(0).Rows.IndexOf(row) + 1
... was to reset intLoop given that I'd just deleted a row, but I keep on getting error:
InvalidOperationException was unhandled
Collection was modified; enumeration operation might not execute.
Re: [2005] Collection was modified; enumeration operation might not execute.
You can't modify a collection within an enumeration block. Don't enumerate.
Code:
While (dsCopyOfDataView.Tables("tblExchangeRates").Rows.Count)
' Modify to your heart's content; length will be checked each time.
End While
Re: [2005] Collection was modified; enumeration operation might not execute.
To begin with, I don;t think you should use For Each in this case, I would go for
[vbcode]
for ctr as int = dsCopyOfDataView.Tables("tblExchangeRates").Rows.count -1 to 0 step -1
'code to test and remove
Next
[/vbode]
However, I think I've read somewhere that you shouldn't remove items from a collection that you're looping. You could alternatively add a temporary column such as "ToDelete", set a flag in first pass and then delete the rows that have been marked as "Y" in the ToDelete column.
Re: [2005] Collection was modified; enumeration operation might not execute.
Thanks for your replies.
Quote:
I think I've read somewhere that you shouldn't remove items from a collection that you're looping
I'd like to use Penagate's suggestion as I need to remove the rows. I had thought of using Mr No's suggestion, but I think I'd have the same problem (i.e. deleting all rows flagged as "for deletion"), plus I'd have to loop through everything again - doubling the processing time.
So, now my code looks like:
Code:
While (dsCopyOfDataView.Tables("tblExchangeRates").Rows.Count)
'For Each row In dsCopyOfDataView.Tables("tblExchangeRates").Rows
strCurrentSearchString = dsCopyOfDataView.Tables("tblExchangeRates").Rows(intLoop)(5)
'MsgBox(dsCopyOfDataView.Tables(0).Rows.IndexOf(row).ToString)
If strPreviousSearchString = strCurrentSearchString Then
strPreviousSearchString = strCurrentSearchString
dsCopyOfDataView.Tables("tblExchangeRates").Rows.RemoveAt(intLoop)
End If
strPreviousSearchString = strCurrentSearchString
intLoop = HOW DO I GET THE CURRENT ROW NUMBER
'Next
End While
... But I don't know how to get the row number from the data table so that I can assign a value to intLoop, and therefore RemoveAt(intLoop)
Using Intellisense, the IndexOf requires a DataRow passing to it, but now I'm not using 'row', and I think I need to be using an integer.
Thanks in advance for your advice.
Re: [2005] Collection was modified; enumeration operation might not execute.
Ah... you don't need to get the row ID though. Assuming they're consecutive and zero-based, you can do it with a bit of logic:
Start with row zero:
If it's bad: delete it; still working with row zero.
OR if it's good: leave it; now working with row 1.
Repeat.
Get the drift?
Re: [2005] Collection was modified; enumeration operation might not execute.
Use a counter and looping backwards as Mr. No suggested... For Each isn't helpful in this case, so don't use it.
Re: [2005] Collection was modified; enumeration operation might not execute.
Replying to penagate:
I think I get the idea, but I've still got some gaps in my knowledge.
Doesn't it still need to know which row index to RemoveAt, and don't I still need to assign a value to strCurrentSearchString so that I can compare it with strPreviousSearchString?
Re: [2005] Collection was modified; enumeration operation might not execute.
What exactly does this search string do? I can't wrap my feeble brain around it.
Re: [2005] Collection was modified; enumeration operation might not execute.
Thanks Mr No and Stanav. This works brilliantly.
Thanks to Penagate for your input.