Enumerable.Sum lève une nouvelle exception OverflowException pour certaines entrées
.NET 8 ajoute la prise en charge de la vectorisation dans les méthodes Enumerable.Sum le cas échéant. L’effet secondaire de ce changement est que l’implémentation vectorisée peut changer l’ordre dans lequel les différents éléments sont ajoutés. Bien que cela ne change pas le résultat final des exécutions réussies, cela peut entraîner des exceptions OverflowException inattendues pour certains ensembles d’entrées pathologiques.
Comportement précédent
Prenez le code suivant :
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);
}
}
Avant ce changement, le code précédent imprimait la sortie suivante :
0
0
OverflowException
OverflowException
Nouveau comportement
Depuis .NET 8, l’extrait de code de la section Comportement précédent imprime la sortie suivante :
0
OverflowException
OverflowException
0
Version introduite
.NET 8 Preview 7
Type de changement cassant
Ce changement est un changement de comportement.
Raison du changement
Ce changement a été effectué pour tirer parti de la vectorisation dans les API LINQ.
Action recommandée
Si votre code est impacté par le changement, vous pouvez :
Désactiver complètement la vectorisation dans votre application en définissant la variable d’environnement
DOTNET_EnableHWIntrinsic
sur 0.Écrire une méthode
Sum
personnalisée qui n’utilise pas la vectorisation :static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }