首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不一致行为:在foreach循环中调用时,List<T>.Sort方法中不会引发任何异常。

不一致行为:在foreach循环中调用时,List<T>.Sort方法中不会引发任何异常。
EN

Stack Overflow用户
提问于 2017-01-13 13:30:52
回答 2查看 180关注 0票数 8

我们知道,如果在foreach循环中更改集合,将引发以下异常:

InvalidOperationException:集合已被修改;枚举操作可能不会执行。

但是有一种行为不同的方法:List.Sort(Comparison)

例如(dotnetfiddle.net):

代码语言:javascript
复制
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,我们可以看到在这个特定方法中没有版本增量,而在上面的方法中有一个版本增量:

代码语言:javascript
复制
public void Sort(int index, int count, IComparer<T> comparer) {
    ...
    _version++;
}

版本也在修改列表的所有其他方法中递增。

我的问题是:

  1. 是虫子吗?还是有什么原因造成这种行为?
  2. 如果是个窃听器,为什么这么多年都没修好?

据我所知,大约8-9年前,我曾向微软发布过这份bug报告,但遭到了拒绝。现在我再也找不到了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-02 07:23:56

这是一个bug,这就是为什么在最新的源代码中修复它的原因。

https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Collections/Generic/List.cs#L986

代码语言:javascript
复制
    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中也有类似的错误,它不会抛出修改过的异常,我确实报告了它,他们拒绝了,但是在后续版本中它是固定的。

票数 2
EN

Stack Overflow用户

发布于 2017-02-02 07:03:07

我不知道为什么会这样,虽然我坚信这是出于某种原因而故意的。

如果您查看源代码这里,您将注意到它与使用IComparer<T>的其他排序方法不同,因为它不会增加列表的版本。

现在,这个确切的版本编号告诉foreach语句枚举被更改了,所以如果它没有改变,那么它就意味着在考虑foreach的范围内没有变化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41635772

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档