Aracılığıyla paylaş


Enumerable.Sum bazı girişler için yeni bir OverflowException fırlatır.

.NET 8, uygun olduğunda yöntemlere Enumerable.Sum vektörleştirme desteği ekler. Bu değişikliğin yan etkisi olarak, vektörleştirilmiş uygulama farklı öğelerin eklenme sırasını değiştirebilir. Bu, başarılı çalıştırmalarda nihai sonucu değiştirmese de, belirli patolojik giriş kümeleri için beklenmeyen OverflowException özel durumlara neden olabilir.

Önceki davranış

Aşağıdaki kodu inceleyin:

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

Bu değişiklik öncesinde, yukarıdaki kod aşağıdaki çıkışı yazdırdı:

0
0
OverflowException
OverflowException

Yeni davranış

.NET 8 ile birlikte, Önceki davranış bölümündeki kod parçacığı aşağıdaki çıktıyı verir:

0
OverflowException
OverflowException
0

Sürüm kullanıma sunulmuştur

.NET 8 Önizleme 7

Kesinti yaratan değişiklik türü

Bu değişiklik davranışsal bir değişikliktir.

Değişiklik nedeni

Bu değişiklik LINQ API'lerinde vektörleştirmeden yararlanmak için yapılmıştır.

Kodunuz değişiklik tarafından etkileniyorsa şunları yapabilirsiniz:

  • Ortam değişkenini 0 olarak ayarlayarak vektörleştirmeyi DOTNET_EnableHWIntrinsic uygulamanızda tamamen devre dışı bırakın.

  • Vektörleştirme kullanmayan özel Sum bir yöntem yazın:

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

Etkilenen API'ler