Enumerable.Sum genera una nuova eccezione OverflowException per alcuni input
.NET 8 aggiunge il supporto per la vettorizzazione nei metodi Enumerable.Sum, se applicabile. Come effetto collaterale di tale modifica, l'implementazione vettorializzata può modificare l'ordine in cui vengono aggiunti i diversi elementi. Anche se questo non dovrebbe modificare il risultato finale nelle esecuzioni riuscite, può causare eccezioni impreviste OverflowException per determinati set di input patologici.
Comportamento precedente
Osservare il codice seguente:
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);
}
}
Prima di questa modifica, il codice precedente ha stampato l'output seguente:
0
0
OverflowException
OverflowException
Nuovo comportamento
A partire da .NET 8, il frammento di codice della sezione Comportamento precedente stampa l'output seguente:
0
OverflowException
OverflowException
0
Versione di introduzione
.NET 8 Preview 7
Tipo di modifica che causa un'interruzione
Questa è una modifica funzionale.
Motivo della modifica
Questa modifica è stata apportata per sfruttare i vantaggi della vettorizzazione nelle API LINQ.
Azione consigliata
Se il codice è interessato dalla modifica, è possibile:
Disabilitare completamente la vettorializzazione nell'applicazione impostando la variabile di ambiente
DOTNET_EnableHWIntrinsic
su 0.Scrivere un metodo personalizzato
Sum
che non usa la vettorializzazione:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }