为什么Count()方法要使用"checked"关键字?

24

我在查阅 Count和Count()之间的区别时,想看一下Count()的源代码。我看到以下代码片段,不明白为什么需要使用checked关键字:

int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        num = checked(num + 1);
    }
    return num;
}

源代码:

// System.Linq.Enumerable
using System.Collections;
using System.Collections.Generic;

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
    }
    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }
    IIListProvider<TSource> iIListProvider = source as IIListProvider<TSource>;
    if (iIListProvider != null)
    {
        return iIListProvider.GetCount(onlyIfCheap: false);
    }
    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num = checked(num + 1);
        }
        return num;
    }
}

2
.NET 4.0 还没有这个检查,但是 4.5 有了。这使得避免与 WinRT 迭代器 发生问题的可能性相当大,请注意它们使用 uint。 - Hans Passant
1个回答

36

因为在序列中有超过20亿个项目的情况下,它不希望返回负数(尽管这种情况很少见),或者在序列中有超过40亿个项目的情况下返回非负数但是错误的数字(即使这种情况更加罕见)。checked将检测溢出条件。


1
@DavidMårtensson C#默认为 unchecked; 可以通过编译器开关在全局级别将其翻转为 checked - 但是坦率地说,我很少见到它被使用,因此认为建议C#通常在checked模式下运行是非常错误的; 还请注意,unsafeunchecked没有任何互动。 - Marc Gravell
1
这对我来说是个新闻,我在编写之前在一个项目中进行了测试,C# 抱怨溢出,直到我加上 unchecked。编辑:找到了我看到的答案 “对于常量表达式(可以在编译时完全评估的表达式),默认上下文始终为 checked。除非将常量表达式明确放置在 unchecked 上下文中,否则在表达式的编译时评估期间发生的溢出会导致编译时错误。” - David Mårtensson
@DavidMårtensson 啊,是的 - 很好的细微差别; 我在谈论运行时; 正如你所说:编译时是不同的。 - Marc Gravell
但是编译时间不适用于帖子示例,所以我的评论是不正确的,我已经删除了它。 - David Mårtensson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接