不一致的行为:List<T>.Sort 方法在 foreach 循环中调用时没有抛出异常
Inconsistent behavior: no exception is thrown in the List<T>.Sort method when called in a foreach loop
我们知道,如果我们在 foreach
循环中更改集合,则会抛出以下异常:
InvalidOperationException: Collection was modified; enumeration operation may not execute.
但是有一种方法的行为不同:List<T>.Sort(Comparison<T>)
。
例如(dotnetfiddle.net):
List<int> list = new List<int> { 2, 1 } ;
foreach (int i in list)
{
//list.Sort(Comparer<int>.Default); // InvalidOperationException
//list.Sort(); // InvalidOperationException
list.Sort((a, b) => a.CompareTo(b)); // No exception
Console.WriteLine(i);
}
根据referencesource.microsoft.com我们可以看到在这个特定的方法中没有版本增量,而在上面的方法中有一个:
public void Sort(int index, int count, IComparer<T> comparer) {
...
_version++;
}
版本也会在所有其他修改列表的方法中递增。
我的问题是:
- 这是一个错误吗?或者这种行为有某种原因?
- 如果它是一个错误,为什么多年没有修复?
我记得大约 8-9 年前我曾向 Microsoft 发布过此错误报告,但被拒绝了。现在我找不到了。
我不知道为什么它会这样,但我坚信它出于某种原因是故意的。
如果您查看源代码 here,您会注意到它与使用 IComparer<T>
的其他排序方法不同,因为它不会增加列表的版本。
现在,这个确切的 version numbering 告诉 foreach
可枚举已更改的语句,因此如果它没有更改,那么就 foreach
而言就意味着没有更改被考虑。
这是一个错误,这就是它在最新源代码中修复的原因。
public void Sort(Comparison<T> comparison) {
if( comparison == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
}
Contract.EndContractBlock();
if (_size > 1) {
ArraySortHelper<T>.Sort(_items, 0, _size, comparison);
}
_version++;
}
类似的bug可能还有很多,除非有人举报,而且被认为是非常危险的,否则它们仍然存在,因为它们不是优先事项。
不用担心,在List.ForEach
中也有类似的错误,不会抛出Modified Exception,我确实报告过,他们拒绝了,但在后续版本中修复了。
我们知道,如果我们在 foreach
循环中更改集合,则会抛出以下异常:
InvalidOperationException: Collection was modified; enumeration operation may not execute.
但是有一种方法的行为不同:List<T>.Sort(Comparison<T>)
。
例如(dotnetfiddle.net):
List<int> list = new List<int> { 2, 1 } ;
foreach (int i in list)
{
//list.Sort(Comparer<int>.Default); // InvalidOperationException
//list.Sort(); // InvalidOperationException
list.Sort((a, b) => a.CompareTo(b)); // No exception
Console.WriteLine(i);
}
根据referencesource.microsoft.com我们可以看到在这个特定的方法中没有版本增量,而在上面的方法中有一个:
public void Sort(int index, int count, IComparer<T> comparer) {
...
_version++;
}
版本也会在所有其他修改列表的方法中递增。
我的问题是:
- 这是一个错误吗?或者这种行为有某种原因?
- 如果它是一个错误,为什么多年没有修复?
我记得大约 8-9 年前我曾向 Microsoft 发布过此错误报告,但被拒绝了。现在我找不到了。
我不知道为什么它会这样,但我坚信它出于某种原因是故意的。
如果您查看源代码 here,您会注意到它与使用 IComparer<T>
的其他排序方法不同,因为它不会增加列表的版本。
现在,这个确切的 version numbering 告诉 foreach
可枚举已更改的语句,因此如果它没有更改,那么就 foreach
而言就意味着没有更改被考虑。
这是一个错误,这就是它在最新源代码中修复的原因。
public void Sort(Comparison<T> comparison) {
if( comparison == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
}
Contract.EndContractBlock();
if (_size > 1) {
ArraySortHelper<T>.Sort(_items, 0, _size, comparison);
}
_version++;
}
类似的bug可能还有很多,除非有人举报,而且被认为是非常危险的,否则它们仍然存在,因为它们不是优先事项。
不用担心,在List.ForEach
中也有类似的错误,不会抛出Modified Exception,我确实报告过,他们拒绝了,但在后续版本中修复了。