为什么 C# 中的大括号让人头疼?
您是否曾经编写过 C# 代码,想要输出类似 {名字}: {值} 的文本,却反而得到了 FormatException?如果是这样,您并不孤单。关于 “How to escape curly brace in String.Format” 的问题在 Stack Overflow 上获得了数万次浏览。这并非偶然:C# 中的大括号 {} 具有特殊含义——它们表示变量替换的位置。
但是,如果您需要将大括号本身作为普通字符输出,该怎么办?例如,用于 JSON、模板、代码生成或仅仅是为了美化报告格式?今天,我们将从头到尾讨论这个主题:从简单的转义到使用 StringBuilder 和字符串插值的高级技巧。
如何转义大括号:基本规则
答案简单而优雅:将大括号加倍。如果您想输出一个左大括号 {,请写 {{。对于右大括号 },请写 }}。C# 会理解这不是占位符,而是普通字符。
这是一个最简单的例子:
string result = string.Format("大括号中的值: {{0}}", 42);Console.WriteLine(result);// 输出: 大括号中的值: {0}请注意:{{0}} 不是占位符,而是一对转义的大括号,里面包含数字 0。如果我们写 {0},则会得到变量的值(数字 42)。
新手典型错误
初学者经常这样写:
// 错误!string bad = string.Format("你好, {name}!", name);// FormatException: Input string was not in a correct format.为什么?因为 C# 期望大括号内是数字索引({0}、{1}),而不是变量名。对于变量名,需要使用字符串插值(见下文)或显式指定索引。
实践示例:从简单到复杂
让我们分析几个需要转义大括号的真实场景。
1. 出于调试目的输出 JSON 或 XML
假设您正在编写一个日志记录器,并希望输出带有值替换的 JSON 字符串:
int userId = 101;string json = string.Format("{{\\"userId\\": {0}, \\"name\\": \\"Alice\\"}}", userId);Console.WriteLine(json);// 输出: {"userId": 101, "name": "Alice"}这里的 {{ 和 }} 创建了 JSON 的外部大括号,而 {0} 替换为数字。
2. 生成代码模板
假设您正在用 C# 编写一个代码生成器。需要为另一种语言(例如 Python 或 JavaScript)创建一个包含模板的字符串:
string template = string.Format("def {0}(): return {{0}}", "calculate");Console.WriteLine(template);// 输出:// def calculate():// return {0}请注意:输出字符串中的 {{0}} 不再是 C# 的占位符,而是生成代码的一部分(例如,用于 Python)。
3. 混合多个占位符和大括号的格式化
当需要混合替换和转义时,关键是不要混淆索引:
string name = "Bob";int age = 30;string message = string.Format("用户 {{ {0} }} (年龄: {1})", name, age);Console.WriteLine(message);// 输出: 用户 { Bob } (年龄: 30)这里的 {{ 产生 {,}} 产生 },而 {0} 和 {1} 替换为值。
String.Format 的替代方案:字符串插值和 StringBuilder
虽然 string.Format 是经典方法,但在现代 C# 中有更方便的方式。让我们比较一下。
字符串插值 (C# 6+)
字符串插值是在字符串前使用 $ 的魔法。它可读性更好,但大括号转义仍然存在