Delen via


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.

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;
    }
    

Betrokken API's