Jaime Stuardo

Hello

I have the following foreach loop:

foreach (string variable in _variables.Keys)

{

double fx = ObtieneValorParametro(variable, poliza, periodo);

if (_variables[variable] == null)

_variables[variable] = fx;

}

Where _variables is of Dictionary<string, object> type.

The only modification to the collection I'm making is to change the value of an element from null to a value, as you see. I'm not removing nor adding elements, so, why I receive that error I tried by using a traditional for loop, but since the collection is a Dictionary<string, object> collection I couldn't access the elements by mean of their indices.

Any help woul be greatly appreciated

Thanks

Jaime




Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

John Arlen

You are changing the contents of the list during enumeration which is the no-no being reported.

A better way to handle would be to enumerate as you are, but keep second list of the "null" values. When done, populate them as needed:

List<string> nullVariables = new List<string>();
foreach(....)
{
if (_var[var] == null)
secondList.Add(var);
}


foreach(string item in secondList)
{
_var[var] = Calculate(var);
}





Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

ArtySaravana

Jaime,

The reason you see this is The IEnumerator returned by the underlying collection may expose Current property as read-only.Generally you should avoid changes to collections(in fact most cases you will not even be able to change the collection) using for--each.

There is a small caveat to this. Consider the below example:

You will see that the line in pink is allowed while the line in green is not. So I am actaully able to change the referenced object's value but not the actual reference itself.

This makes absolute sense, as the collection just holds on to the address of the key and the value objects and does not really care what changes in their topology.

Hopefully this helps you understand what is happenning.

dict[key].name = key.ToLower();

dict[key]= new Emp(key.ToLower());

class Emp

{

public string name;

public Emp(string n)

{

name = n;

}

}

static void Main(string[] args)

{

Dictionary<string, Emp> dict = new Dictionary<string, Emp>();

dict.Add("A", new Emp("A"));

dict.Add("B", new Emp("B"));

dict.Add("C", new Emp(""));

dict.Add("D", new Emp(""));

foreach (string key in dict.Keys)

{

if (dict[key].name==string.Empty)

{

try

{

//dict[key].name = key.ToLower();

dict[key]= new Emp(key.ToLower());

Console.WriteLine("Key " + key + ", Value :" + dict[key].name);

}

catch (InvalidOperationException ie)

{

Console.WriteLine(ie.Message);

}

}

}

Console.ReadLine();

}






Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

Meidan Alon

Or you could something like:

private void Update<K>(Dictionary<K, float> dict, float sum)

{

   foreach (K key in new List<float>(dict.Keys))

   {

       dict[key] = dict[key] / sum;

   }

}





Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

PhilippG

i have something similar here, related to ToolStripMenuItem, ToolStripItem, etc.

please see the following code snippet/sample (using c# .net 2.0):

void Test()
{
ToolStripMenuItem sourceMenu = new ToolStripMenuItem( "source_root" );
sourceMenu.DropDownItems.Add( new ToolStripMenuItem( "source.A" ) );
sourceMenu.DropDownItems.Add( new ToolStripMenuItem( "source.B" ) );

ToolStripMenuItem targetMenu = new ToolStripMenuItem( "target_root" );
foreach (ToolStripMenuItem menuItem in sourceMenu.DropDownItems)
{
System.Diagnostics.Debug.Write(
"source: " + sourceMenu.DropDownItems.Count + "; " +
"target: " + targetMenu.DropDownItems.Count );

//the following will remove the item from the source!

//this leads to enumeration exception in foreach loop!
targetMenu.DropDownItems.Add( menuItem );

System.Diagnostics.Debug.Write(
"source: " + sourceMenu.DropDownItems.Count + "; " +

"target: " + targetMenu.DropDownItems.Count );

}
}


any ideas

kind regards, philipp

keywords: .net dotnet c# csharp foreach enumeration framework





Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

JohnArlen

This is the exact same problem as above, but indirectly - which is why it's not so obvious. You are changing the contents of the list being enumerated.

A ToolStripItem can only have one parent. So when you call:

targetMenu.DropDownItems.Add( menuItem );

...it is also resulting in an implicit call to:

sourceMenu.DropDownItems.Remove( menuItem );

The simplest way (in my opinion) is the same as the second suggestion above. Create a List<ToolStripiMenuItem> - populate it as you go

List<ToolStripMenuItem> newItems = new List<ToolStripMenuItem>();

ToolStripMenuItem targetMenu = new ToolStripMenuItem( "target_root" );
foreach (ToolStripMenuItem menuItem in sourceMenu.DropDownItems)
{
System.Diagnostics.Debug.Write(
"source: " + sourceMenu.DropDownItems.Count + "; " +
"target: " + targetMenu.DropDownItems.Count );

newItems.Add( menuItem );

System.Diagnostics.Debug.Write(
"source: " + sourceMenu.DropDownItems.Count + "; " +

"target: " + targetMenu.DropDownItems.Count );

}

foreach( ToolStripMenuItem newItem in newItems )

{

targetMenu.DropDownItems.Add(newItem);

}
}





Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

PhilippG

thank you very much!

i wasn't aware of the fact that the parent of the source is being changed.

and in conclusion, that the DropDownItem will implicitly get removed from the source!

i really don't like implicit (and thereby "invisible") conventions Wink

by the way:

in unmanaged / native code (c++), the visual studio has a debug option "new breakpoint: new DATA breakpoint".

i was hoping to trace down who is removing that item from source and why.

but unfortunately, these "data breakpoints" are not available for managed code (c#).

is there something similar for managed code

i.e. automatically break when someone / something modifies the variable XYZ

kind regards, philipp





Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

Dinesh Rathi

private void Update<K>(Dictionary<K, float> dict, float sum)

{

foreach (K key in new List<float>(dict.Keys))

{

dict[key] = dict[key] / sum;

}

}

this is exact solution to add or remove some items from the collections.

thanx to give exact solution.

Dinesh Rathi






Re: .NET Base Class Library "Collection was modified; enumeration operation may not execute." error

sicikim

Hello,

I have a similar problem, but the difference is that I don't want to modify anything. The first version of my code was:

Principal miPadre = (Principal)this.MdiParent;
foreach (ToolStripItem toolStripItem in miPadre.MainMenuStrip.Items)
{
if (toolStripItem.Text.CompareTo("Secciones") == 0)
toolStripItem.Enabled = false;
}

The first day that I tried it, it works fine but then I got the error. Then just to test the code I made this:

Principal miPadre = (Principal)this.MdiParent;
foreach (ToolStripItem toolStripItem in miPadre.MainMenuStrip.Items)
{
MessageBox.Show(toolStripItem.Text);
}

As you can see, I'm not modifying nothing and the error is still there. Any idea


Thank you very much,

Kim