运行此代码时:
var list = new List<string>
{
"foo",
"bar",
};
foreach (var l in list)
{
Console.WriteLine(l);
list.Add("bar");
}引发异常:
System.InvalidOperationException:集合已被修改;枚举操作可能不会执行。
.NET如何知道集合是在枚举器迭代该集合时被修改的?集合对象中是否有此标志?
发布于 2017-01-10 10:28:49
List<T>内部将其“版本”保存在整数变量中。对列表的每次修改(添加、删除、排序、清除、.)将此版本增加一个。
现在,List<T>的枚举数在初始化时保存此版本号。对于每个MoveNext(),即每次迭代,它都检查列表的版本号是否仍然等于保存的版本号。
这样,它就可以检测列表何时在两次迭代之间被修改。注意,这个实现会导致一个带有整数溢出的特殊错误:Why this code throws 'Collection was modified', but when I iterate something before it, it doesn't?。
Sort(Comparison<T> comparison)似乎也有一个bug,它不会增加版本号。此代码:
var list = new List<string>
{
"foo",
"bar",
};
foreach (var l in list)
{
Console.WriteLine(l);
list.Sort((x, y) => x.CompareTo(y));
}指纹:
foo
foo发布于 2017-01-10 10:27:19
是的,典型的解决方案是一个标志、版本值等,例如在List<T>的情况下。
https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646
这是一个版本
private int _version;例如。
public bool MoveNext() {
...
return MoveNextRare()
}
private bool MoveNextRare()
{
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}https://stackoverflow.com/questions/41566484
复制相似问题