不再转义、不再拼接——所见即所得的多行字符串
// ① 转义地狱:每个引号加反斜杠
var json = "{\"name\":\"Alice\"}";
// ② 拼接地狱:多行字符串用 +
var sql = "SELECT Id " +
"FROM Users " +
"WHERE Status = 1";
// ③ Verbatim(@)只解决一半
var xml = @"<item name=""book""/>";
// 引号还是要双双写
// 所见即所得——至少三个双引号
var json = """
{"name": "Alice"}
""";
var sql = """
SELECT Id
FROM Users
WHERE Status = 1
""";
var xml = """
<item name="book"/>
""";
| 规则 | 说明 |
|---|---|
至少三个 " | 开始/结束各至少 3 个双引号——"""...""" 或 """"..."""" |
内容中 " 少于包裹数就安全 | 内容含 3 个连续引号 → 用 4 个 """" 包裹;内容含 4 个 → 用 5 个……以此类推 |
开始 """ 后必须换行 | 内容从下一行开始——"""Hello""" 不合法(开始引号后无换行) |
| 自动缩进修剪 | 编译器以结束标记的缩进为基准,去掉每行前面共同的空白 |
| 支持内插 | $"""...{x}..."""——内插正常使用;$$"""...{{x}}..."""——减少花括号冲突 |
// 你写(结束 """ 在第 4 列缩进):
var text = """
Line 1
Line 2
Line 3
""";
// 编译器:结束 """ 从第 4 列开始 → 基准缩进 = 4 格 → 每行去掉 4 格
// Line 1
// Line 2 ← 这行额外 4 格保留(相对于基准缩进)
// Line 3
""" 的位置。如果结束标记在深层缩进里(如 8 格),每行都去掉 8 格。如果某行实际少于 8 格空白——编译器报错。
// 正常写法:结束 """ 独占一行 → 末尾自动包含 \r\n
var s = """
hello
"""; // → "hello\r\n" ← 末尾有换行
// 无末尾换行:结束 """ 紧跟内容 → 缩进修剪失效
var s = """
hello"""; // → " hello" ← 缩进保留了!基准=0
// 折衷:正常写,末尾 Trim
var s = """
hello
""".TrimEnd("\r\n"); // → "hello" ← TrimEnd 对 ReadOnlySpan 零分配
""" 独占一行——三者只能取其二。大多数场景(JSON、SQL、HTML)末尾多个换行不碍事。
// 你写:
var json = """
{"name": "Alice"}
""";
// 编译器生成(简化):
// - 编译时完成缩进去除(纯编译器预处理)
// - IL:ldstr "{\"name\": \"Alice\"}\r\n"
// - 和手写转义字符串完全一样的 IL
// - 内插版本 → DefaultInterpolatedStringHandler(和普通 $"..." 一样)
Raw String Literal 是纯粹的编译时预处理。IL 和手写转义字符串一模一样——它只是让你写的时候不用转义。
\r\n:源文件 Windows 换行(CRLF)就是内容的一部分。编译器只修剪缩进空格/制表符,不修剪换行符——因为换行符是你敲的 Enter,是内容的分隔符。
// ✅ 单元测试中的期望 JSON
var expected = """
{
"id": 1,
"name": "Alice"
}
""";
// ✅ SQL 查询模板
var sql = """
SELECT u.Id, u.Name, o.Total
FROM Users u
JOIN Orders o ON u.Id = o.UserId
WHERE u.Status = @status
""";
// ✅ $ 内插——配合 JSON/XML 使用
var name = "Alice";
var json = $"""
{{ "name": "{name}", "ts": "{DateTime.Now:O}" }}
"""; // $ + """ → {name} 是内插,字面 { 需 {{ 转义
// ✅ $$ 内插——避免和 JSON 花括号冲突
var json2 = $$"""
{ "name": "{{name}}", "count": {{count}} }
"""; // $$ → {{name}} 是内插,{ 是字面
var s = """Hello"""; 能编译吗?$"""...""" 和 $$"""...""" 的区别是?"{\"..." 和 @"..." 字符串——用 Raw String Literal 重写。