標準數值格式剖析精確度
使用 ToString
和 TryFormat
將數位格式化為字串時,.NET 現在支援更高的精確度值。
注意
精確度上限在 .NET 7 中再次變更。 如需詳細資訊,請參閱數值格式字串的最大精確度。
變更描述
將數位格式化為字串時,格式字串中的精確度指定名稱代表結果字串中的位數。 根據格式指定名稱,也就是字串開頭的字元,精確度可以代表數位總數、精確度或十進位數。
在舊版 .NET 中,標準數值格式剖析邏輯僅限於 99 或更少的精確度。 某些數數值型別具有更高的精確度,但 ToString(string format)
無法正確公開。 例如,如果您指定大於 99 的精確度,例如 32.ToString("C100")
,則格式字串會解譯為自訂數值格式字串,而不是「精確度為 100 的貨幣」。 在自訂數值格式字串中,字元會解譯為字元常值。 此外,包含無效格式指定名稱的格式字串會根據精確度值以不同的方式解譯。 H99
對於無效格式指定名稱擲回 FormatException,而 H100
解譯為自訂數值格式字串。
從 .NET 6 開始,.NET 支援高達 Int32.MaxValue 的精確度。 由具有任何位數的格式指定名稱組成的格式字串會解譯為具有精確度的標準數值格式字串。 針對下列任和一項或兩項條件擲回 FormatException:
- 格式指定名稱字元不 標準格式指定名稱。
- 精確度大於 Int32.MaxValue。
這項變更是在影響所有數數值型別的剖析邏輯中實作。
下表顯示各種格式字串的行為變更。
格式化字串 | 先前的行為 | .NET 6+ 行為 |
---|---|---|
C2 |
表示具有兩個十進位數的貨幣 | 表示具有兩個十進位數的貨幣 (無變更) |
C100 |
表示列印「C100」的自訂數值格式字串 | 表示具有 100 個十進位數的貨幣 |
H99 |
因為標準格式指定名稱「H」無效而擲回 FormatException | 因為標準格式指定名稱「H」無效而擲回 FormatException (無變更) |
H100 |
表示自訂數值格式字串 | 因為標準格式指定名稱「H」無效而擲回 FormatException |
導入的版本
.NET 6
變更原因
數值格式剖析使用較高的精確度時,這項變更會修正非預期的行為。
建議的動作
在大部分情況下,不需要採取任何動作,而且產生的字串中會顯示正確的精確度。
不過,如果您想要還原為先前的行為,當精確度大於 99 時,格式指定名稱會解譯為常值字元,您可以使用單引號括住該字元,也可以使用反斜線將該字元逸出。 例如,在舊版 .NET 中,42.ToString("G999")
會傳回 G999
。 若要維護該行為,請將格式字串變更為 "'G'999"
或 "\\G999"
。 這適用於 .NET Framework、.NET Core 和 .NET 5+。
下列格式字串會繼續解譯為自訂數值格式字串:
- 從不是 ASCII 字母字元的任何字元開始,例如
$
或è
。 - 從不是後面接著 ASCII 數位的 ASCII 字母字元開始,例如
A$
。 - 從 ASCII 字母字元開始,後面接著 ASCII 位數序列,然後是不是 ASCII 位數字元的任何字元,例如
A12A
。
受影響的 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.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)