LINQ总和OverflowException异常?(LINQ Sum OverflowExcept

2019-06-25 11:42发布

我实现了EventLogEntry一个自定义的IEqualityComparer。

public class EventLogEntryListComparison :
    IEqualityComparer<List<EventLogEntry>>,
    IEqualityComparer<EventLogEntry>

对于IEqualityComparer<List<EventLogEntry>>中,GetHashCode的功能很简单。

public int GetHashCode(List<EventLogEntry> obj)
{
    return obj.Sum(entry => 23 * GetHashCode(entry));
}

然而,这将引发对某些项目的OverflowException异常。

"Arithmetic operation resulted in an overflow."
   at System.Linq.Enumerable.Sum(IEnumerable`1 source)
   at System.Linq.Enumerable.Sum[TSource](IEnumerable`1 source, Func`2 selector)
   at <snip>.Diagnostics.EventLogAnalysis.EventLogEntryListComparison.GetHashCode(List`1 obj) in C:\dev\<snip>Diagnostics.EventLogAnalysis\EventLogEntryListComparison.cs:line 112
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
   at <snip>.Diagnostics.EventLogAnalysis.Program.AnalyseMachine(String validMachineName) in C:\dev\<snip>.Diagnostics.EventLogAnalysis\Program.cs:line 104
   at System.Threading.Tasks.Parallel.<>c__DisplayClass2d`2.<ForEachWorker>b__23(Int32 i)
   at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()

努力后能得到同样的错误,而调试和不能在即时窗口,我改变了代码,这一点,再见OverflowException异常?

int total = 0;
foreach (var eventLogEntry in obj)
{
    total += GetHashCode(eventLogEntry);
}

return total;

它是如何LINQ的Sum函数行为不同?

编辑2

多亏了几点意见,修正和预期的GetHashCode现在的功能有:

public int GetHashCode(List<EventLogEntry> obj)
{
    return unchecked(obj.Aggregate(17,
        (accumulate, entry) =>
        accumulate * 23 + GetHashCode(entry)));
}

Answer 1:

LINQ的Enumerable.Sum(...)方法执行一个内部的补充checked块。 这意味着,如果总和溢出,他们故意抛出异常。

您的总和不是内部checked块,那么它是否会抛出异常取决于......无论是从内部调用checked块,或相信大会的属性。



Answer 2:

这是因为大会于C#编写的不同的行为和执行Enumerable.Sum

如果您在C#编译大会,默认情况下,所有添加在执行unchecked模式,这就是为什么你没有得到你的最后一个例子溢出。 如果你想运行扔在溢出,你需要使用checked块(当然你的哈希,你希望出现这种情况,所以C#的默认行为是罚款)。

相比之下, Enumerable.Sum是为了计算总和,通常情况下,你不希望资金溢出。 这就是为什么Enumerable.Sum在执行其计算的checked模式,如果总和溢出会抛出异常。



Answer 3:

如果你正在计算哈希码,你可能不希望反正用点心。 使用XOR( ^ )将提供相同的结果,甚至可能蔓延的散列码出超过总和会。 试试这个方法:

public int GetHashCode(List<EventLogEntry> obj)
{
    int total = 0;
    foreach (var eventLogEntry in obj)
    {
        total ^= GetHashCode(eventLogEntry);
    }

    return total;
}


文章来源: LINQ Sum OverflowException?