다음을 통해 공유


Enumerable.Sum이 일부 입력에 대해 새로운 OverflowException을 throw함

.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

호환성이 손상되는 변경의 형식

이 변경 사항은 동작 변경입니다.

변경 이유

이 변경 내용은 LINQ API의 벡터화를 활용하기 위해 수행되었습니다.

코드가 변경의 영향을 받는 경우 다음 중 하나를 수행할 수 있습니다.

  • DOTNET_EnableHWIntrinsic 환경 변수를 0으로 설정하여 애플리케이션에서 벡터화를 모두 사용하지 않도록 설정합니다.

  • 벡터화를 사용하지 않는 사용자 지정 Sum 메서드를 작성합니다.

    static int Sum(IEnumerable<int> values)
    {
        int acc = 0;
        foreach (int value in values)
        {
            checked { acc += value; }
        }
        return acc;
    }
    

영향을 받는 API