问题
Hey, I'm using the Enumerable.Sum()
extension method from LINQ to compute hash codes, and am having a problem with OverflowExceptions
when the code gets big. I tried putting the call in an unchecked
block, but that didn't seem to help.
The MSDN documentation for the method says it will throw if the value gets too big, but I checked in reflector and this is all there is:
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;
}
Based on this decompilation, I would expect it to either overflow or not depending on the context of the calling code. Why is it overflowing, and how can I get it to stop?
回答1:
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
- Switch to a larger type such as
long
- Write your own version of Sum which does not use checked addition
回答2:
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;
}
}
回答3:
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
来源:https://stackoverflow.com/questions/2208827/enumerable-sum-overflowing