字符串.format中的转义花括号会丢失。可能是C#的一个Bug?

3

我有一个MSVC 2012的MCVE:

using System;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string [] args)
        {
            string result = string.Format(@"{{{0:G};{1:G}}}", foo(), bar());
            Console.WriteLine(result);
        }

        private static string foo() { return "foo"; }
        private static string bar() { return "bar"; }
    }
}

期望输出:{foo;bar}

结果:{foo;bar

将格式字符串更改为@"{{{0:G};{1:G} }}"(添加一个空格)可以产生正确的输出。这是可能的错误吗?或者为什么转义的闭合花括号没有显示?


1
Soner Gönül 给出了一个好的答案。问题在于数据是按顺序解释或按顺序评估,没有树形结构或表达式。我不知道微软是否只是找到了解决问题的最简单方法,还是还有其他原因。也许数据科学家可以回答这个问题。 - Bassam Alugili
1个回答

6

来自复合格式化中转义大括号部分

开放和关闭的大括号被解释为开始和结束一个格式项。因此,您必须使用转义序列来显示文字形式的开放或闭合的大括号。在固定文本中指定两个开放的大括号(“{{”)以显示一个开放的大括号(“{”),或者指定两个闭合的大括号(“}}”)以显示一个闭合的大括号(“}”)。格式项中的大括号按照遇到它们的顺序逐个解释。不支持解释嵌套的大括号。

转义大括号的解释方式可能导致意想不到的结果。例如,考虑格式项"{{{0:D}}}",该项旨在显示一个开放的大括号,一个格式化为十进制数的数字值以及一个闭合的大括号。然而,实际上解释这个格式项的方式如下:

  • 前两个开放的大括号(“{{”)被转义并产生一个开放的大括号。

  • 接下来的三个字符(“{0:”)被解释为格式项的开始。

  • 下一个字符(“D”)会被解释为十进制标准数字格式规范符,但接下来的两个转义大括号(“}}”)产生一个单独的大括号。因为生成的字符串(“D}”)不是标准数字格式规范符,所以结果字符串被解释为自定义格式字符串,它表示显示文字形式的字符串“D}”。

  • 最后一个大括号(“}”)被解释为格式项的结束。

  • 显示的最终结果是文字形式的字符串“{D}”。要格式化的数值未显示。

避免误解转义大括号和格式项的一种编码方式是将大括号和格式项分开格式化

因此,您应该这样使用它;

string result = string.Format(@"{0}{1:G};{2:G}{3}", "{", "foo", "bar", "}");

谢谢你的回答。然而,我认为这是一个错误,因为一些C#构建器很懒惰。没有任何理由让C#编译器表现出这种行为。 - Peter VARGA
@AlBundy 我对“bug”持怀疑态度,因为它在文档中有说明,但这些大括号可能会让词法分析器/标记生成器感到困惑。在我看来,这可能是原因。我会尽快向.NET团队询问此问题。 - Soner Gönül
你可以通过将错误添加到文档中来“合法化”一个bug。在这方面,苹果是这个宇宙的大师 [比如握手机姿势不正确导致天线问题]。无论如何,我已经给你的答案点赞并接受了它。这只是我的私人意见。 - Peter VARGA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接