代码改变世界

C# 中格式化字符串中包含 { 或者 } 如何转义?

2007-07-18 23:24  晓风残月  阅读(8384)  评论(4编辑  收藏  举报

C# 中使用类似 {0}, {1:yyyy-MM-dd} 这样的格式占位符,如果被格式化字符串本身包含 { 或者 } 怎么办呢?答案是:用两个 { 或者 }连写表示单个。

例如

string str1 = String.Format("{{Hello}}, {0}, Now is {{{1:yyyy-MM-dd HH:mm:ss}}}""Jinglecat", DateTime.Now); // {Hello}, Jinglecat, Now is {2007-07-18 23:06:35} 
        
//string str2 = String.Format("{Hello}, {0}, Now is {{1:yyyy-MM-dd HH:mm:ss}}", "Jinglecat", DateTime.Now); // --> System.FormatException: 输入字符串的格式不正确。

事实上,很多情况下带特殊含义的字符都是这样转义的:
如,

C#  中,当字符串常量带 @  前导的时候,用两个 " 连写表示一个 " (半角双引号)
 string str3 = @"My UserName is ""Jinglecat""."; // My UserName is "Jinglecat". 
        
//string str4 = @"My UserName's "Jinglecat""; // error CS1002: 应输入 ;
        //string str5 = @"My UserName
's \"Jinglecat\""; // error CS1002: 应输入 ;
见:总结 @ 在 C# string 中的用法

SQL 字符串常量,用两个 ' 连写表示一个 ' (半角单引号)

DECLARE @str6 varchar(100)
SET @str6 = 'My UserName is ''Jinglecat''.' 
PRINT @str6 -- My UserName is 'Jinglecat'.

正则表达式中用,两个 $ 连写表示一个 $  (dollar)

PS:其实自己很早就知道了 C# 中 @ 和 SQL 中双单引号的用法,却没有想到 {和}也可以这样转义,还在CSDN “郑重其事”发了帖子讨论,惭愧啊
不过,至少说明,群众的智慧是无穷的,感谢 CSDN 众多朋友^_^
String.Format 中能转义 { & } 吗? 

update 2007年7月19日
终于在 MSDN 这一主题给翻出来了
复合格式化 转义大括号
http://msdn2.microsoft.com/zh-cn/library/txafckwd(VS.80).aspx
转义大括号
左大括号和右大括号被解释为格式项的开始和结束。因此,必须使用转义序列显示文本左大括号或右大括号。在固定文本中指定两个左大括号 (
"{{") 以显示一个左大括号 ("{"),或指定两个右大括号 ("}}") 以显示一个右大括号 ("}")。按照在格式项中遇到大括号的顺序依次解释它们。不支持解释嵌套的大括号。 

解释转义大括号的方式会导致意外的结果。例如,考虑要显示一个左大括号、一个格式化为十进制数的数值和一个右大括号的格式项“{{{
0:D}}}”。但是,实际是按照以下方式解释该格式项: 

前两个左大括号 (
"{{") 被转义,生成一个左大括号。 

之后的三个字符 (
"{0:") 被解释为格式项的开始。

下一个字符 (
"D") 将被解释为 Decimal 标准数值格式说明符,但后面的两个转义大括号 ("}}") 生成单个大括号。由于得到的字符串 ("D}") 不是标准数值格式说明符号,所以得到的字符串会被解释为用于显示字符串“D}”的自定义格式字符串。 

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

显示的最终结果是字符串“{D}”。不会显示本来要格式化的数值。

在编写代码时,避免错误解释转义大括号和格式项的一种方法是单独格式化大括号和格式项。也就是说,在第一个格式化操作中显示文本左大括号,在下一操作中显示格式项的结果,然后在最后一个操作中显示文本右大括号。


但是,让你令人疑惑的是,按 MSDN 的解释,{{{索引[,对齐][:格式字符串]}}}  这样的格式化是否无法得到预期格式化的,但是,我的测试结果显示对于时间却是可以的

        string str8 = String.Format("{{{0:D}}} {{{1:yyyy-MM-dd HH:mm:ss}}}"911, DateTime.Now); // {D} {2007-07-19 13:30:05}