A Curious Halfwit HashSet Bug
On Friday I came into work and was greeted with an unhandled exception dialog from Halfwit. I clicked the "Debug" button to drop into Visual Studio, and saw the following stack trace:
{"Collection was modified; enumeration operation may not execute."}
at System.Collections.Generic.HashSet`1.Enumerator.MoveNext()
at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()
at System.Collections.Generic.HashSet`1.ExceptWith(IEnumerable`1 other)
at Halfwit2.ViewModels.MainViewModel.AddUserNames(IEnumerable`1 userNames)
It didn't give me line numbers, but that's ok, because the AddUserNames method is really simple:
internal void AddUserNames(IEnumerable<String> userNames)
{
_userNames.UnionWith(userNames);
if (_userNames.Count > 5000)
{
_userNames.ExceptWith(
_userNames.Take(_userNames.Count - 5000));
}
}
So my _userNames field, which is a HashSet<String>, has a whole bunch of user names added to it. If it winds up being bigger than 5000 names, I remove the first couple to bring the set size back down to 5000.
Can you see the bug?
The problem is that the parameter I'm passing in, _userNames.Take(...), is a "live" IEnumerable. I imagine that ExceptWith is doing something like this:
foreach (var item in list)
{
if (this.Contains(item)) this.Remove(item);
}
However, the act of removing the item from the set will have modified the "list" that I've passed in (since I'm passing in the same set that I'm modifying)!
The fix is really simple:
_userNames.ExceptWith(
_userNames.Take(_userNames.Count - 5000).ToList());
By adding a .ToList() call to the end of the Take, I'm telling to to convert the results into a separate list, so the iteration of the list inside the ExceptWith call will be independent of what happens to the set.
This is one of those little "gotchas" you can hit when playing with Linq extension methods. Always be aware that you're requerying the same list whenever you use a method like Take or Skip!
Trackbacks
- A Curious Halfwit HashSet Bug « Mas-Tool's Favorites | http://mas-tool.com/?p=2761
- All About Computer - Windows Client Developer Roundup 070 for 5/23/2011 | http://ispey.com/computer/computer/windows-client-developer-roundup-070-for-5232011/
- Linksammlung 12/6/2011 | Silverlight, WPF & .NET | http://www.ebnerj.at/blog/?p=1171
Comments
No comments yet. Be the first!