C#字符串格式化应优先用$插值和ToString();ToString("F2")适用于确定性数值格式控制,如金额四舍五入;插值中格式须紧贴右括号,支持对齐与条件但需注意空格和括号;String.Format()仅用于日志模板或动态格式;所有格式化默认依赖当前文化,固定格式需显式指定CultureInfo.InvariantCulture。

直接说结论:C# 字符串格式化有 4 种主流方式,但日常开发中真正该优先用的只有 $(字符串插值)和 ToString();String.Format() 已逐步退居二线,仅在动态拼接或旧代码维护时才需主动处理。
什么时候必须用 ToString("F2") 而不是插值?
当你需要对单个数值做**确定性、可复用、带文化感知的格式控制**时,ToString() 最稳。比如金额四舍五入到两位小数、整数补零、科学计数法输出等,它不依赖外部参数顺序,也不受插值表达式复杂度影响。
- 错误写法:
$"{price:F2}"看似简洁,但若price是null或decimal?且未判空,会抛NullReferenceException - 正确做法:先确保非空,再调用
price.ToString("F2"),或用空合并:price?.ToString("F2") ?? "0.00" -
"D6"这类整数补零格式只支持ToString(),插值里不能直接写${n:D6}(语法错误),必须写成${n.ToString("D6")} - 性能上,
ToString("C")比$"{n:C}"略快——因为后者底层仍会调用前者,还多一层解析开销
$"..." 中怎么安全嵌入格式、对齐和条件?
字符串插值是目前最自然的写法,但它不是万能的“套娃容器”,容易因符号混淆出错。
- 格式部分必须紧贴右括号:
${value:0.00}✅,${value :0.00}❌(冒号前不能有空格) - 字段宽度和对齐用逗号:
${name,12}(右对齐占 12 位)、${name,-12}(左对齐) - 条件判断必须包括号:
${(score >= 60 ? "Pass" : "Fail")},漏括号会编译失败 - 要显示字面量
{或},得写两个:{{和}};@$""和$@""效果一样,都支持原生字符串语义 - 避免在插值里写复杂表达式,比如
${list.FirstOrDefault(x => x.Id == id)?.Name ?? "N/A"}—— 可读性差,调试困难,建议提前赋值变量
String.Format() 还值得学吗?
值得,但只在两种场景下:一是日志模板(如 "User {0} logged in from {1} at {2:HH:mm:ss}"),二是需要运行时拼接格式字符串(比如从配置读取 "{0:C} ({1:P1})" 再传参)。
- 常见陷阱:
String.Format("x={0}, y={1}", x)参数数量不足 → 抛FormatException:“索引(从零开始)必须大于或等于零,且小于参数列表的大小。” - 位置索引可以重复或乱序:
String.Format("{1} and {0} and {1}", "A", "B")→"B and A and B" - 不要用它格式化日期或数字——
DateTime.Now.ToString("yyyy-MM-dd")更明确,也更容易单元测试 - .NET 6+ 中,
string.Create()在高性能场景(如高频日志)中替代String.Format(),但普通业务几乎用不到
为什么 Console.WriteLine("x={0}", x) 不算“过时”,但也不推荐用于业务逻辑?
这是复合格式化(composite formatting)的典型用法,底层复用 String.Format() 逻辑。它方便快捷,但缺乏类型安全和 IDE 支持。
- 编译期不检查参数个数或类型,运行时报错才暴露问题
- 无法被 Roslyn 分析器有效约束,比如误写
Console.WriteLine("{0:C}", "abc"),不会报错,但输出是"abc:C"(原样照打) - 在日志库(如 Serilog)中已被结构化日志取代:
Log.Information("User {@User} logged in", user),这才是现代做法 - 如果只是临时调试输出,它完全够用;但进到 Service 层或 DTO 序列化前的字符串组装,必须用
ToString()或插值
最容易被忽略的一点:所有格式化行为都默认依赖 CultureInfo.CurrentCulture,比如 "C" 格式在中文系统输出 ¥100.00,英文系统是 $100.00。如果你在导出报表或 API 响应中需要固定格式,务必显式传入 CultureInfo.InvariantCulture,例如 amount.ToString("C", CultureInfo.InvariantCulture)。


















