Abhijit Ojha
Abhijit Ojha

Reputation: 479

collection was modified enumeration operation might not execute with foreach loop

DataRow.Delete() is working fine in one method but not working in another method.

//Working method
public static bool finalThrustHDForce(int startPoint, int nPlotSelection)
{
    int startVal = 1;
    try
    {
        foreach (DataRow dr in dtThrustCalc.Rows)
        {
            if ((startVal = Convert.ToInt32(dr[ThrustCalculation.pathLength]) - startPoint) < 0)
                dr.Delete();
            else
                dr[ThrustCalculation.pathLength] = startVal;
        }
        dtThrustCalc.AcceptChanges();
        calculateBreadkDown();
        calculateCriticalPoints(nPlotSelection);
    }
    catch (Exception ex) { ex.Log(); return false; }
    return true;
}
// not working , getting error collection was modified enumeration operation //might not execute

Upvotes: 0

Views: 1377

Answers (2)

Alex Essilfie
Alex Essilfie

Reputation: 12613

The Cause

You're getting that message because to enumerate a collection using foreach requires that the collection does not get changed (i.e. no addition or removal of elements) until the enumeration is completed. By deleting a data row from the collection, you violate this requirement and hence the error.

The Solution

Create a list of items to be deleted and then delete them after having done the first iteration.

var toDelete = new List<DataRow>();

foreach (DataRow dr in dtThrustCalc.Rows)
{
    if ((startVal = Convert.ToInt32(dr[ThrustCalculation.pathLength]) - startPoint) < 0)
        toDelete.Add(dr);
    else
        dr[ThrustCalculation.pathLength] = startVal;
}

foreach (var dr in toDelete)
    dtThrustCalc.Rows.Remove(dr); // not so sure of this as I'm using my phone

This method uses a bit more memory to store a cache of the items to be deleted.

The alternative is to use a reverse for loop and delete the items as you encounter them.

for (var i = dtThrustCalc.Rows.Count - 1; i >= 0; i--)
{
    var dr = dtThrustCalc[i];
    if ((startVal = Convert.ToInt32(dr[ThrustCalculation.pathLength]) - startPoint) < 0)
        dr.Delete();
    else
        dr[ThrustCalculation.pathLength] = startVal;
}

By traversing the collection in reverse, you're assured that you'll not skip any items even when you remove some items midstream.

Upvotes: 0

Richardissimo
Richardissimo

Reputation: 5773

The error is telling you that the collection of things that you are iterating through using foreach has been modified within that loop. Consider not deleting it at that point, and making a list of things to delete. Then delete those things after the foreach has finished.

Upvotes: 1

Related Questions