Enumerable.Sum genereert nieuwe OverflowException voor sommige invoer
.NET 8 voegt ondersteuning toe voor vectorisatie in de Enumerable.Sum methoden, indien van toepassing. Als neveneffect van deze wijziging kan de gevectoriseerde implementatie de volgorde wijzigen waarin de verschillende elementen worden toegevoegd. Hoewel dit niet het uiteindelijke resultaat in geslaagde uitvoeringen moet wijzigen, kan dit leiden tot onverwachte OverflowException uitzonderingen voor bepaalde sets pathologische invoer.
Vorig gedrag
Kijk eens naar de volgende code:
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);
}
}
Vóór deze wijziging heeft de voorgaande code de volgende uitvoer afgedrukt:
0
0
OverflowException
OverflowException
Nieuw gedrag
Vanaf .NET 8 wordt in het codefragment uit de sectie Vorig gedrag de volgende uitvoer afgedrukt:
0
OverflowException
OverflowException
0
Versie geïntroduceerd
.NET 8 Preview 7
Type wijziging die fouten veroorzaken
Deze wijziging is een gedragswijziging.
Reden voor wijziging
Deze wijziging is aangebracht om te profiteren van vectorisatie in LINQ-API's.
Aanbevolen actie
Als uw code wordt beïnvloed door de wijziging, kunt u het volgende doen:
Schakel vectorisatie helemaal uit in uw toepassing door de
DOTNET_EnableHWIntrinsic
omgevingsvariabele in te stellen op 0.Schrijf een aangepaste
Sum
methode die geen vectorisatie gebruikt:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }