数値書式指定文字列の最大有効桁数
ToString
と TryFormat
を使用する文字列として数値を書式設定するときの最大有効桁数が Int32.MaxValue から 999,999,999 に変更されました。 (.NET 6 で最大有効桁数が Int32.MaxValue に以前変更されました)
また、文字列の BigInteger を解析するときに許可される最大指数が 999,999,999 に制限されました。
以前の動作
.NET 6 では、標準の数値書式解析ロジックは Int32.MaxValue 以下の有効桁数に制限されていました。 本来の動作は、Int32.MaxValue より大きい有効桁数に対して FormatException をスローするというものでした。 ただし、バグのために、.NET 6 ではそのような入力に対してその例外がスローされませんでした。 本来の動作は次のようなものでした。
double d = 123.0;
d.ToString("E" + int.MaxValue.ToString()); // Doesn't throw.
long intMaxPlus1 = (long)int.MaxValue + 1;
string intMaxPlus1String = intMaxPlus1.ToString();
Assert.Throws<FormatException>(() => d.ToString("E" + intMaxPlus1String)); // Throws.
また、文字列から BigInteger を解析するとき、指数サイズに制限はありませんでした。
新しい動作
.NET 7 以降では、.NET でサポートされる有効桁数は最大 999,999,999 です。 有効桁数が 999,999,999 を超える場合、FormatException がスローされます。 この変更は、すべての数値型に影響を与える解析ロジックで実装されました。
double d = 123.0;
Assert.Throws<FormatException>(() => d.ToString("E" + int.MaxValue.ToString())); // Throws.
long intMaxPlus1 = (long)int.MaxValue + 1;
string intMaxPlus1String = intMaxPlus1.ToString();
Assert.Throws<FormatException>(() => d.ToString("E" + intMaxPlus1String)); // Throws.
d.ToString("E999999999"); // Doesn't throw.
d.ToString("E00000999999999"); // Doesn't throw.
また、指数が 999,999,999 を超える BigInteger を文字列から解析しようとすると、FormatException がスローされます。
導入されたバージョン
.NET 7
破壊的変更の種類
この変更は、バイナリの互換性に影響を与える可能性があります。
変更理由
.NET 6 で導入された動作は、有効桁数が Int32.MaxValue より大きいときに FormatException をスローするというものでした。 ただし、バグのため、最大値を超える入力に対してその例外はスローされませんでした。 この変更により、有効桁数を 999,999,999 に制限することでバグが修正されます。
推奨される操作
ほとんどの場合、書式指定文字列で 999,999,999 を超える有効桁数を既に使用していることは考えられないため、いかなる操作も必要ありません。
影響を受ける API
この変更は、すべての数値型に影響を与える解析ロジックで実装されました。
- System.Numerics.BigInteger.ToString(String)
- System.Numerics.BigInteger.ToString(String, IFormatProvider)
- System.Numerics.BigInteger.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Int32.ToString(String)
- System.Int32.ToString(String, IFormatProvider)
- System.Int32.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.UInt32.ToString(String)
- System.UInt32.ToString(String, IFormatProvider)
- System.UInt32.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Byte.ToString(String)
- System.Byte.ToString(String, IFormatProvider)
- System.Byte.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.SByte.ToString(String)
- System.SByte.ToString(String, IFormatProvider)
- System.SByte.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Int16.ToString(String)
- System.Int16.ToString(String, IFormatProvider)
- System.Int16.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.UInt16.ToString(String)
- System.UInt16.ToString(String, IFormatProvider)
- System.UInt16.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Numerics.BigInteger.Parse
- System.Numerics.BigInteger.TryParse
- System.Int64.ToString(String)
- System.Int64.ToString(String, IFormatProvider)
- System.Int64.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.UInt64.ToString(String)
- System.UInt64.ToString(String, IFormatProvider)
- System.UInt64.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Half.ToString(String)
- System.Half.ToString(String, IFormatProvider)
- System.Half.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Single.ToString(String)
- System.Single.ToString(String, IFormatProvider)
- System.Single.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Double.ToString(String)
- System.Double.ToString(String, IFormatProvider)
- System.Double.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
- System.Decimal.ToString(String)
- System.Decimal.ToString(String, IFormatProvider)
- System.Decimal.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)
関連項目
.NET