内插字符串格式问题
Interpolated string formatting issue
我已经多次偶然发现一个与内插字符串有关的问题。
考虑以下情况:
double number = 123.4567;
var str = $"{{{number:F2}}}"; //I want to get "{123.45}"
Console.WriteLine(str); // Will print "{F2}"
起初有点惊讶,但一旦你意识到大括号是如何配对的,它就有意义了。接下来的两个大括号是内插字符串中单个大括号的转义序列。所以内插表达式的左括号与字符串中的最后一个花括号配对。
___pair____
| |
$"{{{number:F2}}}";
现在您可以执行以下操作来中断转义序列:
var str = $"{{{number:F2} }}"; // This will be "{123.45 }"
注意此方法添加到输出中的 space 字符。 (不理想)
我的问题:
假设我想使用 单个内插字符串 来准确获得输出“{123.45}”
如果不做像下面这样的骇人听闻的事情,这是完全可能的吗?
var s = $"{{{number:F2}{'}'}";
这是字符串插值的预期行为。 this Microsoft 文档中提到了它。以下内容仅来自微软link。
左大括号和右大括号被解释为开始和结束格式项。因此,您必须使用转义序列来显示原义的左大括号或右大括号。在固定文本中指定两个左大括号 ("{{")
以显示一个左大括号 ("{")
,或指定两个右大括号 ("}}")
以显示一个右大括号 ("}")
。格式项中的大括号按遇到它们的顺序依次解释。不支持解释嵌套大括号。
转义大括号的解释方式可能会导致意外结果。例如,考虑格式项“{{{0:D}}}”,它旨在显示左大括号、格式化为十进制数字的数值和右大括号。但是,格式项实际上是按以下方式解释的:
- 前两个左大括号
("{{")
被转义并产生一个
左大括号。
- 接下来的三个字符
("{0:")
被解释为一个
格式项。
- 下一个字符
("D")
将被解释为十进制标准
数字格式说明符,但接下来的两个转义大括号 ("}}")
产生一个大括号。因为结果字符串 ("D}")
不是
标准数字格式说明符,结果字符串是
解释为自定义格式字符串,表示显示文字
字符串 "D}"
.
- 最后一个大括号
("}")
被解释为格式项的结尾。
- 显示的最终结果是文字字符串,
"{D}"
。这
未显示要格式化的数值。
编写代码以避免误解转义大括号和格式项的一种方法是分别格式化大括号和格式项。也就是说,在第一个格式化操作中显示文字左大括号,在下一个操作中显示格式项的结果,然后在最后一个操作中显示文字右大括号。以下示例说明了这种方法。
int value = 6324;
string output = string.Format("{0}{1:D}{2}",
"{", value, "}");
Console.WriteLine(output);
// The example displays the following output:
// {6324}
假设不需要使用命名格式字符串,可以使用:
var s = $"{{{number:#.#0}}}";
我已经多次偶然发现一个与内插字符串有关的问题。
考虑以下情况:
double number = 123.4567;
var str = $"{{{number:F2}}}"; //I want to get "{123.45}"
Console.WriteLine(str); // Will print "{F2}"
起初有点惊讶,但一旦你意识到大括号是如何配对的,它就有意义了。接下来的两个大括号是内插字符串中单个大括号的转义序列。所以内插表达式的左括号与字符串中的最后一个花括号配对。
___pair____
| |
$"{{{number:F2}}}";
现在您可以执行以下操作来中断转义序列:
var str = $"{{{number:F2} }}"; // This will be "{123.45 }"
注意此方法添加到输出中的 space 字符。 (不理想)
我的问题:
假设我想使用 单个内插字符串 来准确获得输出“{123.45}”
如果不做像下面这样的骇人听闻的事情,这是完全可能的吗?
var s = $"{{{number:F2}{'}'}";
这是字符串插值的预期行为。 this Microsoft 文档中提到了它。以下内容仅来自微软link。
左大括号和右大括号被解释为开始和结束格式项。因此,您必须使用转义序列来显示原义的左大括号或右大括号。在固定文本中指定两个左大括号 ("{{")
以显示一个左大括号 ("{")
,或指定两个右大括号 ("}}")
以显示一个右大括号 ("}")
。格式项中的大括号按遇到它们的顺序依次解释。不支持解释嵌套大括号。
转义大括号的解释方式可能会导致意外结果。例如,考虑格式项“{{{0:D}}}”,它旨在显示左大括号、格式化为十进制数字的数值和右大括号。但是,格式项实际上是按以下方式解释的:
- 前两个左大括号
("{{")
被转义并产生一个 左大括号。 - 接下来的三个字符
("{0:")
被解释为一个 格式项。 - 下一个字符
("D")
将被解释为十进制标准 数字格式说明符,但接下来的两个转义大括号("}}")
产生一个大括号。因为结果字符串("D}")
不是 标准数字格式说明符,结果字符串是 解释为自定义格式字符串,表示显示文字 字符串"D}"
. - 最后一个大括号
("}")
被解释为格式项的结尾。 - 显示的最终结果是文字字符串,
"{D}"
。这 未显示要格式化的数值。
编写代码以避免误解转义大括号和格式项的一种方法是分别格式化大括号和格式项。也就是说,在第一个格式化操作中显示文字左大括号,在下一个操作中显示格式项的结果,然后在最后一个操作中显示文字右大括号。以下示例说明了这种方法。
int value = 6324;
string output = string.Format("{0}{1:D}{2}",
"{", value, "}");
Console.WriteLine(output);
// The example displays the following output:
// {6324}
假设不需要使用命名格式字符串,可以使用:
var s = $"{{{number:#.#0}}}";