How do you return a copy of original List<T> from Func<T, TResult>?
Question
I have found out (in a hard way) that a collection that is being enumerated cannot be modified within "Foreach" statement
"Collection was modified; enumeration operation may not execute."
Now, the solution I came up with is to create a dummy collection of the same size that contains a dictionary key and enumerate over it to modify collection in question.
private void InvalidateAuthenticatedNodes()
{
var dummy = new Dictionary<int, bool>(_AuthenticatedNodes.Count);
foreach (var nodeId in _AuthenticatedNodes.Keys)
dummy[nodeId] = false;
foreach (var nodeId in dummy.Keys)
_AuthenticatedNodes[nodeId] = false;
ClearAuthenticatedDateTime();
}
Above code worked fine; I was in process of refactoring above code to use a Func delegate to return a copy of keys as following
private void InvalidateAuthenticatedNodes()
{
var getNodeIds =
new Func<Dictionary<int, bool>, IEnumerable<int>>(
nodes => nodes.Select(node => node.Key));
foreach (var nodeId in getNodeIds(_AuthenticatedNodes))
{
_AuthenticatedNodes[nodeId] = false;
}
ClearAuthenticatedDateTime();
}
Unlike what I have expected, getNodeIds does not return a copy. Is there a way to return a copy instead?
*EDIT: Temporary Result before JaredPar's answer
Similar to JaredPar's answer but his was more concise and I went with his answer. But here is the similar result I came up with to share.
private void InvalidateAuthenticatedNodes()
{
var getNodeIds =
new Func<Dictionary<int, bool>, IEnumerable<int>>(nodes =>
nodes.Select(node => node.Key));
foreach (var nodeId in getNodeIds(_AuthenticatedNodes).ToList())
{
_AuthenticatedNodes[nodeId] = false;
}
ClearAuthenticatedDateTime();
}
*EDIT: Final Result (refined)
_AuthenticatedNodes.Keys.ToList().ForEach(
nodeId => _AuthenticatedNodes[nodeId] = false);
Solution
Just add a .ToList() to the end of the collection and it will automagically return a complete copy of the list.
foreach (var nodeId in _AuthenticatedNodes.Keys.ToList())
...
OTHER TIPS
Instead of using a foreach, you could use a normal for. However, be careful when adding/removing items, it changes the indexes of the elements inside the collection.
Once you change an Enumerable class, your original enumerator may become invalid, thus the need to create a copy and make your modifications there.