Funkcja Enumerable.Sum zgłasza nowy wyjątek OverflowException dla niektórych danych wejściowych
Platforma .NET 8 dodaje obsługę wektoryzacji w metodach tam Enumerable.Sum , gdzie ma to zastosowanie. Jako efekt uboczny tej zmiany implementacja wektoryzowana może zmienić kolejność dodawania różnych elementów. Chociaż nie powinno to zmienić końcowego wyniku w pomyślnych przebiegach, może to spowodować nieoczekiwane OverflowException wyjątki dla niektórych zestawów patologicznych danych wejściowych.
Poprzednie zachowanie
Spójrzmy na poniższy kod:
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);
}
}
Przed tą zmianą powyższy kod wydrukował następujące dane wyjściowe:
0
0
OverflowException
OverflowException
Nowe zachowanie
Począwszy od platformy .NET 8, fragment kodu z poprzedniej sekcji zachowania wyświetla następujące dane wyjściowe:
0
OverflowException
OverflowException
0
Wprowadzona wersja
.NET 8 (wersja zapoznawcza 7)
Typ zmiany powodującej niezgodność
Ta zmiana jest zmianą behawioralną.
Przyczyna wprowadzenia zmiany
Ta zmiana została wprowadzona w celu wykorzystania wektoryzacji w interfejsach API LINQ.
Zalecana akcja
Jeśli twój kod ma wpływ na zmianę, możesz wykonać następujące czynności:
Wyłącz wektoryzacja całkowicie w aplikacji, ustawiając zmienną
DOTNET_EnableHWIntrinsic
środowiskową na 0.Napisz metodę niestandardową
Sum
, która nie używa wektoryzacji:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }