Enumerable.Sum создает новый Метод OverflowException для некоторых входных данных
.NET 8 добавляет поддержку векторизации в методах Enumerable.Sum , где применимо. В качестве побочных эффектов этого изменения векторная реализация может изменить порядок добавления различных элементов. Хотя это не должно изменить окончательный результат успешных запусков, это может привести к непредвиденным OverflowException исключениям для определенных наборов патологических входных данных.
Прежнее поведение
Рассмотрим следующий код:
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);
}
}
Перед этим изменением предыдущий код напечатал следующие выходные данные:
0
0
OverflowException
OverflowException
Новое поведение
Начиная с .NET 8 фрагмент кода из раздела "Предыдущее поведение " выводит следующие выходные данные:
0
OverflowException
OverflowException
0
Представленные версии
.NET 8( предварительная версия 7)
Тип критического изменения
Причина изменения
Это изменение было сделано для использования векторизации в API LINQ.
Рекомендуемое действие
Если код влияет на изменение, можно выполнить следующие действия:
Отключите векторизацию полностью в приложении, задав
DOTNET_EnableHWIntrinsic
переменную среды значение 0.Напишите пользовательский
Sum
метод, который не использует векторизацию:static int Sum(IEnumerable<int> values) { int acc = 0; foreach (int value in values) { checked { acc += value; } } return acc; }