Enumerable.Sum() overflowing

試著忘記壹切 提交于 2019-11-30 11:51:14

The code is indeed executing in a C# checked block. The problem is that reflector doesn't properly decompile checked blocks and instead shows them as normal mathmatical operations. You can verify this yourself by creating a checked block, compiling the code and then decompiling it in reflector.

You can also verify this by looking at the IL instead of the decompiled C# code. Instead of the add IL opcode you'll see that the addition occurs with add.ovf. This is the version of add that throws on overflows

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 

There is no way to get this particular method to not throw on overflow. Your best options are the following

  1. Switch to a larger type such as long
  2. Write your own version of Sum which does not use checked addition

I wrote this function for generic enumerables. I'd love to hear any remarks about it.

public static int SequenceHashCode<T>(IEnumerable<T> seq)
{
    unchecked
    {
        return seq != null ? seq.Aggregate(0, (sum,obj) => sum+obj.GetHashCode()) : 0;
    }
}

checked only applies to expressions in the current block, not any (already-compiled) called method. To use unchecked maths, you'll need to implement your own version of Sum inside an unchecked block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!