Enumerable.Sum vyvolá novou výjimku OverflowException pro některé vstupy
.NET 8 přidává podporu vektorizace v Enumerable.Sum metodách, pokud je to možné. Jako vedlejší účinek této změny může vektorizovaná implementace změnit pořadí, ve kterém jsou přidány různé prvky. I když by nemělo dojít ke změně konečného výsledku úspěšných spuštění, může to vést k neočekávaným OverflowException výjimkám pro určité sady patologických vstupů.
Předchozí chování
Uvažujte následující kód:
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);
}
}
Před touto změnou vytiskl předchozí kód následující výstup:
0
0
OverflowException
OverflowException
Nové chování
Od verze .NET 8 vypíše fragment kódu z předchozí části chování následující výstup:
0
OverflowException
OverflowException
0
Zavedená verze
.NET 8 Preview 7
Typ zásadní změny
Tato změna je změna chování.
Důvod změny
Tato změna byla provedena tak, aby využívala vektorizaci v rozhraních LINQ API.
Doporučená akce
Pokud má změna vliv na váš kód, můžete:
Zakažte vektorizaci v aplikaci tak, že nastavíte proměnnou
DOTNET_EnableHWIntrinsic
prostředí na hodnotu 0.Napište vlastní
Sum
metodu, která nepoužívá vektorizaci:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }