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
GitHub で Microsoft と共同作業する
このコンテンツのソースは GitHub にあります。そこで、issue や pull request を作成および確認することもできます。 詳細については、共同作成者ガイドを参照してください。
.NET