首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Enumerable.Sum()溢出

Enumerable.Sum()溢出
EN

Stack Overflow用户
提问于 2010-02-06 00:55:47
回答 3查看 2.5K关注 0票数 12

嘿,我正在使用LINQ的Enumerable.Sum()扩展方法来计算哈希码,当代码变得很大时,我在使用OverflowExceptions时遇到了问题。我尝试将调用放在unchecked块中,但似乎没有帮助。

该方法的MSDN文档说,如果值变得太大,它将抛出,但我检查了反射器,这就是所有的内容:

代码语言:javascript
复制
public static int Sum(this IEnumerable<int> source) {
    if (source == null) {
        throw Error.ArgumentNull("source");
    }
    int num = 0;
    foreach (int num2 in source) {
        num += num2;
    }
    return num;
}

基于这种反编译,我预计它要么溢出,要么不溢出,这取决于调用代码的上下文。为什么它会溢出,我怎么才能让它停止呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-06 01:01:03

代码实际上是在C# checked块中执行的。问题是反射器没有正确地反编译checked块,而是将它们显示为正常的数学操作。您可以自己验证这一点,方法是创建一个检查块,编译代码,然后在reflector中反编译它。

您还可以通过查看IL而不是反编译的C#代码来验证这一点。您将看到使用add.ovf进行添加操作,而不是添加IL操作码。这是在溢出时抛出的add版本

代码语言:javascript
复制
L_001a: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
L_001f: stloc.1 
L_0020: ldloc.0 
L_0021: ldloc.1 
L_0022: add.ovf <-- This is an overflow aware addition
L_0023: stloc.0 
L_0024: ldloc.2 

没有办法让这个特定的方法不在溢出时抛出。你最好的选择如下

Sum切换到更大的类型,如long

  • Write您自己版本的,它不使用checked
票数 9
EN

Stack Overflow用户

发布于 2013-04-03 20:13:19

我为泛型枚举编写了这个函数。我很乐意听到关于它的任何评论。

代码语言:javascript
复制
public static int SequenceHashCode<T>(IEnumerable<T> seq)
{
    unchecked
    {
        return seq != null ? seq.Aggregate(0, (sum,obj) => sum+obj.GetHashCode()) : 0;
    }
}
票数 7
EN

Stack Overflow用户

发布于 2010-02-06 01:05:31

checked仅适用于当前块中的表达式,而不适用于任何(已编译)调用的方法。要使用未检查的数学,您需要在unchecked块中实现您自己的Sum版本

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

https://stackoverflow.com/questions/2208827

复制
相关文章

相似问题

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