次の方法で共有


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 Preview 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