数字格式字符串的最大精度
使用 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)