Enumerable.Sum lança novo OverflowException para algumas entradas
O .NET 8 adiciona suporte à vetorização nos métodos Enumerable.Sum quando aplicável. Como efeito colateral dessa alteração, a implementação vetorizada pode alterar a ordem na qual os diferentes elementos são adicionados. Embora isso não altere o resultado final em execuções bem-sucedidas, isso pode resultar em exceções OverflowException inesperadas para determinados conjuntos de entradas patológicas.
Comportamento anterior
Considere o seguinte código:
Test(GetEnumerable1()); // Non-vectorizable
Test(GetEnumerable1().ToArray()); // Vectorizable
Test(GetEnumerable2()); // Non-vectorizable
Test(GetEnumerable2().ToArray()); // Vectorizable
static IEnumerable<int> GetEnumerable1()
{
for (int i = 0; i < 32; ++i)
{
yield return 1_000_000_000;
yield return -1_000_000_000;
}
}
static IEnumerable<int> GetEnumerable2()
{
for (int i = 0; i < 32; ++i)
{
yield return 100_000_000;
}
for (int i = 0; i < 32; ++i)
{
yield return -100_000_000;
}
}
static void Test(IEnumerable<int> input)
{
try
{
Console.WriteLine(input.Sum());
}
catch (Exception ex)
{
Console.WriteLine(ex.GetType().Name);
}
}
Antes dessa alteração, o código anterior imprimia a seguinte saída:
0
0
OverflowException
OverflowException
Novo comportamento
A partir do .NET 8, o snippet de código da seção Comportamento anterior imprime a seguinte saída:
0
OverflowException
OverflowException
0
Versão introduzida
Prévia 7 do .NET 8
Tipo de alteração interruptiva
Esta é uma alteração comportamental.
Motivo da alteração
Essa alteração foi feita para aproveitar a vetorização em APIs LINQ.
Ação recomendada
Se o código for afetado pela alteração, você poderá:
Desabilite totalmente a vetorização em seu aplicativo definindo a variável de ambiente
DOTNET_EnableHWIntrinsic
como 0.Escreva um método personalizado
Sum
que não use vetorização:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }