語法速查表
| 前綴 | 名稱 | 核心功能 | 轉義序列 | 插值表達式 |
@ |
逐字字符串 |
關閉轉義,保留換行、縮進、反斜杠原意 |
無效 (按原樣輸出) |
不支持 |
$ |
插值字符串 |
編譯期解析 `{表達式}` 嵌入字符串 |
有效 (需 `\\` 表示反斜杠) |
支持 `{var}`、`{expr}`、`{expr:format}` |
$@ 或 @$ |
插值逐字字符串 |
結合兩者:無轉義 + 支持插值 |
無效 |
支持 |
代碼示例與輸出對比
int a = 1;
string path = @"C:\Users\Admin\Documents"; // 逐字:反斜杠無需轉義
string s1 = "Hello\t{a}"; // 普通:\t 為製表符
string s2 = @"Hello\t{a}"; // 逐字:輸出字面 "Hello\t{a}"
string s3 = $"Hello\t{a}"; // 插值:\t 為製表符,{a} 替換為 1
string s4 = $@"Hello\t{a}"; // 插值逐字:\t 原樣輸出,{a} 替換為 1
Console.WriteLine($"s1: [{s1}]"); // s1: [Hello {a}]
Console.WriteLine($"s2: [{s2}]"); // s2: [Hello\t{a}]
Console.WriteLine($"s3: [{s3}]"); // s3: [Hello 1] (中間有製表符)
Console.WriteLine($"s4: [{s4}]"); // s4: [Hello\t1]
進階插值語法
var user = new { Name = "張三", Age = 25, Score = 98.567 };
// 格式化
Console.WriteLine($"{user.Name,-10} | {user.Age,3} | {user.Score:F1}");
// 輸出: 張三 | 25 | 98.6
// 條件表達式
Console.WriteLine($"狀態: {(user.Age >= 18 ? "成年" : "未成年")}");
// 調試輸出 (C# 10+)
Console.WriteLine($"{user.Name=}"); // 輸出: user.Name=張三
// 自定義插值處理器 (C# 10+ 高級)
[InterpolatedStringHandler]
public struct LogHandler { /* 實現 AppendFormatted/AppendLiteral */ }
void Log(LogHandler handler) { /* 结构化日志 */ }
Log($"User {user.Name} logged in at {DateTime.Now}"); // 零分配、可控格式
性能與編譯原理
$"" 編譯為 `string.Format` 或 `StringBuilder` 鏈調用 (舊版本),C# 10+ 優先使用 `DefaultInterpolatedStringHandler` 結構體,**零分配、原地格式化**,性能接近手寫拼接。
@"" 編譯為普通字符串字面量,無運行時開銷。
- 避免在熱路徑中使用複雜插值表達式 (如 LINQ 查詢),預先計算再插值。
最佳實踐建議
- 文件路徑、正則、JSON、SQL、多行文本 →
@$"" (插值逐字):無需雙重轉義,可直接嵌入變量。
var sql = $@"SELECT * FROM Users WHERE Name = '{name}' AND Age > {age}";
- 日志、UI 顯示、普通拼接 →
$"":利用格式化規格、對齊、條件表達式。
- 純靜態多行常量 →
@"":無插值開銷,編譯期常量折疊。
- 避免 `+` 拼接:除極簡單場景,`$""` 可讀性、性能、類型安全全面優勢。
常見誤區
- 以為 `@` 也支持插值 → 必須加 `$`。
- 插值中大括號輸出字面 `{` → 雙寫 `{{`、`}}`。
$"JSON: {{\"key\": {value}}}"
- 插值表達式中包含冒號 `:` 被誤判為格式化 → 用括號包裹 `
$"Time: {(DateTime.Now)}"`。