c#: Changing a value in a dictionary in a foreach
I was trying to loop through a dictionary,
update it's value if a certain condition was met,
if not remove the item from the dictionary.
(Seems I have done something lke this before, but that's why I blog it, so I can remember next time… :))
Here's my first attempt:
private void FindEditedFieldsNotWorking(Dictionary<string, string> dictionary, Control ctrl)
{
foreach (KeyValuePair<string,string> kvp in dictionary)
{
CheckBox c = ctrl.Controls["chk" + kvp.Key] as CheckBox;
if (c != null && c.Checked)
{
dictionary[kvp.Key] = ctrl.Controls[kvp.Key].Text;
}
else
dictionary.Remove(kvp.Key);
}
}
It compiles ok and seems ok.
Might have a misgiving with removing the item in a loop, but hey it's worth a shot..
When running this I got an exception something like
"Collection was modified; enumeration operation may not execute."
My first thought was that my dictionary.Remove was the culprit, so I put a breakpoint there.
But that was not the case (although that is not supported either in this loop)
It seems that I can't actually change the freakin' value within my foreach loop…!
So I tried the same but this time using just the keys in the loop:
private void FindEditedFieldsNotWorkingEither(Dictionary<string, string> dictionary, Control ctrl)
{
foreach (string Key in dictionary.Keys)
{
CheckBox c = ctrl.Controls["chk" + Key] as CheckBox;
if (c != null && c.Checked)
{
dictionary[Key] = ctrl.Controls[Key].Text;
}
else
dictionary.Remove(Key);
}
}
Still no go, same error.
Eventually I read a little bit about this using google and found that I couldn't do any changes while enumerating.
Here are some links I used:
http://stackoverflow.com/questions/1070766/editing-dictionary-values-in-a-foreach-loop
Seems like a bad design decision has made this a problem for many ppl.
The incling is probably the implisit add functionality when doing dict[key]=value; when key is not existing.
Anyways we have to get around this somehow.
The solution I thought was nicest when I couldn't use the "logic" solution is:
.Net 2.0
private void FindEditedFieldsWorking(Dictionary<string, string> dictionary, Control ctrl)
{
List<string> keys = new List<string>(dictionary.Keys);
foreach (string key in keys)
{
CheckBox c = ctrl.Controls["chk" + key] as CheckBox;
if (c != null && c.Checked)
{
dictionary[key] = ctrl.Controls[key].Text;
}
else
dictionary.Remove(key);
}
}
Almost as nice as the first version, and with the added premium that dictionary.Remove won't be a problem.
Or if you're running .Net 3.0 or higher you could just do this:
private void FindEditedFieldsWorking(Dictionary<string, string> dictionary, Control ctrl)
{
foreach (var key in dictionary.Keys.ToList())
{
CheckBox c = ctrl.Controls["chk" + key] as CheckBox;
if (c != null && c.Checked)
{
dictionary[key] = ctrl.Controls[key].Text;
}
else
dictionary.Remove(key);
}
}
where the ToList does the same as our 2.0 solution, namely creating a temp list to hold the keys.
Nice solution on a not so nice problem.
Hope this helps someone,
it will help me next time anyways :)
Regards
Henri Merkesdal
MERIT
Posted via email from Henris blogg
I am sure this post has helped me save many hours of browsing other related posts just to find what I was looking for. Many thanks!
ReplyDeleteJava training in Chennai
Java training in Bangalore
This comment has been removed by the author.
ReplyDeleteI am happy for sharing on this blog its awesome blog I really impressed. thanks for sharing. Great efforts.
ReplyDeleteSoftgen Infotech is the Best SAP HANA Training in Bangalore located in BTM Layout, Bangalore providing quality training with Realtime Trainers and 100% Job Assistance.
Great article.Good blog.
ReplyDeleteJava training in Chennai
Java training in Bangalore
Java training in Hyderabad
Java Training in Coimbatore
Java Online Training