字符串插值必须同时使用$前缀和{}容器,缺一不可;$"hello name"中name未被包裹在{}内,故不解析为变量而作普通文本输出。

字符串插值不是加个 $ 就能跑通,$ 和 {} 必须同时存在、位置正确,否则要么编译失败,要么变量名原样输出。
为什么 $"Hello name" 不替换变量?
漏掉大括号是高频低级错误。写成 $"Hello name" 时,name 只是普通文本,编译器不解析它;必须写成 $"Hello {name}" 才触发插值。漏掉 $ 前缀更严重:直接报错 CS1056: Unexpected character '$'(C# 语言版本低于 6 时也会这样)。
-
$是开关,没有它,{}就是字面量花括号 -
{}是容器,没有它,表达式无处安放 - 嵌套引号要转义:
$"Name: \"{name}\""或用逐字插值$@"Name: ""{name}"""
{expression:formatString} 格式符必须紧贴右大括号
格式说明符冒号后面不能有空格,{price:F2} 合法,{price: F2} 编译失败。日期、数字、对齐都遵循这个规则。
- 数字货币:
$"{value:C2}"—— 不是$"{value: C2}" - 日期格式:
$"{DateTime.Now:yyyy-MM-dd}"—— 冒号是分隔符,不是字符串内容 - 字段对齐:
$"{text,-10}"左对齐,$"{text,10}"右对齐 -
??默认值后不能接格式符:$"{user?.Name ?? "Anonymous":G}会报错;得拆成$"{(user?.Name ?? "Anonymous"):G}"
null 安全和表达式复杂度要手动控制
插值里写 {user.Name} 遇到 user == null 就崩,但 {user?.Name} 只能输出 null 字符串,不是空或默认值。另外,别在 {} 里塞太重的逻辑。
- 安全写法:
$"{user?.Name ?? "Anonymous"}" - 需格式化默认值时,先计算再插值:
var displayName = user?.Name ?? "Anonymous"; $"User: {displayName:G}" - 避免
$"Total: {items?.Sum(x => x.Price * x.Count) ?? 0:C}"—— 每次拼接都执行一次 LINQ - 自定义类型要支持格式化,得实现
IFormattable或重载ToString(string format)
跨平台输出固定格式时 CultureInvariant 得自己上
插值默认走 CultureInfo.CurrentCulture,$"{1234.56:C}" 在美国是 $1,234.56,在德国是 1.234,56 €。API 返回 JSON 或日志写入文件时,这种不确定性就是 bug。
- 强制不变文化:
$"{1234.56:C2}".Replace(',', '.')是野路子,别这么干 - 正解是用
FormattableString+ToString(IFormatProvider):$"{value:C2}".ToString(CultureInfo.InvariantCulture) - 或者统一在入口设置线程文化:
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture(全局影响,慎用)
真正难的不是语法记不住,而是什么时候该放弃插值——比如循环里拼千条日志,这时候 StringBuilder 不是备选,是必选。










