曾经在Stack Overflow上:C#中长字符串的诅咒
想象一下这种情况。您正在用C#编写配置JSON、SQL查询,或者直接在代码中编写HTML模板。字符串变得很长、很难看,而且完全不可读。您按下回车键来换行……然后得到了一个编译错误。熟悉吗?
Stack Overflow上的问题"Multiline string literal in C#" 已经获得了数万次浏览。这并非偶然。长期以来,C#并不是一个对处理多行文本最友好的语言。但时代在变。在本文中,我们将走完从临时解决方案到C# 11中出现的优雅解决方案的历程。
如果您正在编写C#代码并处理多行字符串字面量,这篇文章将为您节省数小时的搜索时间。我们开始吧!
问题:为什么简单地按回车键是个坏主意?
在C#(以及C++)中,字符串字面量是用引号括起来的字符序列。在这些引号内换行是语法错误。编译器根本无法理解字符串在哪里结束。
以下是错误做法:
// 编译错误!string query = "SELECT * FROM UsersWHERE Age > 18ORDER BY Name";编译器会看到"SELECT * FROM Users——然后就结束了。接下来就是一片混乱。过去,开发人员想尽办法来应对。让我们分析一下解决方案的演变过程。
旧方法:Verbatim string(@-字符串)——救星
首先想到的是verbatim string literal。您只需在左引号前加上@。这会禁用转义序列的解释(双引号""除外)。
但有一个问题:缩进也会成为字符串的一部分。
Verbatim string示例:
string json = @"{ ""name"": ""Alice"", ""age"": 30}";Console.WriteLine(json);输出:
{ "name": "Alice", "age": 30}优点:
- 适用于所有C#版本。
- 无需转义反斜杠(
\\)。
缺点:
- 内部的引号必须加倍(
"")——如果JSON很多,这很糟糕。 - 左侧的缩进(空格/制表符)会进入最终字符串。
- 不能直接与字符串插值(
$)混合使用(但可以使用$@)。
这种方法至今仍然流行,但对于干净的代码来说并不理想。真正的突破发生在C# 11。
最新方法:Raw string literal(C# 11 和 .NET 7+)
从C# 11开始,我们有了raw string literal——字面意思是“原始字符串字面量”。它解决了99%的多行字符串问题。
语法:连续三个或更多双引号(""")。
示例1:无需转义的简单JSON
string json = """ { "name": "Alice", "age": 30 } """;Console.WriteLine(json);输出:
{ "name": "Alice", "age": 30}神奇之处:字符串内部的引号无需加倍!编译器只有在看到连续三个引号时才会知道字符串结束。
示例2:带缩进的SQL查询
string query = """ SELECT u.Name, o.OrderDate FROM Users u JOIN Orders o ON u.Id = o.UserId WHERE o.Status = 'Active' ORDER BY o.OrderDate DESC """;Console.WriteLine(query);关于缩进的重要说明: 结束引号(""")设定了基本缩进级别。所有缩进少于结束引号的字符串行都将被修剪。这允许保持代码的可读性,同时避免用多余的空格弄乱字符串。