C#中的多行字符串文字

有没有一种简单的方法可以在C#中创建多行字符串文字?

这是我现在所拥有的:

string query = "SELECT foo, bar"+ " FROM table"+ " WHERE id = 42";

我知道PHP有

<<<BLOCK
BLOCK;

C#有类似的东西吗?

931795 次浏览

您可以在string前面使用@符号来形成逐字字符串文字

string query = @"SELECT foo, barFROM tableWHERE id = 42";

当您使用此方法时,您也会不必转义特殊字符,除了Jon Skeet的答案中显示的双引号。

它在C#中称为逐字字符串文字,只需将@放在文字之前即可。这不仅允许多行,而且还会关闭转义。例如,你可以这样做:

string query = @"SELECT foo, barFROM tableWHERE name = 'a\b'";

然而,这包括将换行符(使用源中的任何换行符)插入字符串。SQL,这不仅无害,而且可能在您看到字符串的任何地方都没有易读性-但在其他地方可能不需要,在这种情况下,您要么不需要使用多行逐字字符串文字开始,要么从结果字符串中删除它们。

唯一的转义是,如果你想要一个双引号,你必须添加一个额外的双引号符号:

string quote = @"Jon said, ""This will work,"" - and it did!";

另一个需要注意的问题是string. Format中字符串文字的使用。在这种情况下,您需要转义花括号/括号'{'和'}'。

// this would give a format exceptionstring.Format(@"<script> function test(x){ return x * {0} } </script>", aMagicValue)// this contrived example would workstring.Format(@"<script> function test(x)\{\{ return x * {0} }} </script>", aMagicValue)

我发现使用字符串文字的问题是它会让你的代码看起来有点“奇怪”,因为为了不让字符串本身出现空格,它必须完全左对齐:

    var someString = @"Thequickbrownfox...";

恶心。

所以我喜欢使用的解决方案,它使所有内容都与代码的其余部分保持良好的对齐是:

var someString = String.Join(Environment.NewLine,"The","quick","brown","fox...");

当然,如果你只是想在逻辑上拆分SQL语句的行,而实际上并不需要新行,你总是可以用Environment.NewLine代替" "

我还没有看到这个,所以我将在这里发布(如果你有兴趣传递一个字符串,你也可以这样做。)这个想法是,你可以在多行上将字符串分解,并以任何你希望的方式添加自己的内容(也在多行上)。这里“tableName”可以传递到字符串中。

    private string createTableQuery = "";
void createTable(string tableName){
createTableQuery = @"CREATE TABLE IF NOT EXISTS["+ tableName  + @"] ([ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,[Key] NVARCHAR(2048)  NULL,[Value] VARCHAR(2048)  NULL)";}

如果你不想要空格/换行符,字符串添加似乎有效:

var myString = String.Format("hello " +"world" +" i am {0}" +" and I like {1}.",animalType,animalPreferenceType);// hello world i am a pony and I like other ponies.

如果你愿意,你可以运行上面的这里

作为旁注,使用C#6.0,您现在可以将插值字符串与逐字字符串文字组合在一起:

string camlCondition = $@"<Where><Contains><FieldRef Name='Resource'/><Value Type='Text'>{(string)parameter}</Value></Contains></Where>";

为什么人们总是混淆字符串和字符串文字?公认的答案是对另一个问题的很好的回答;不是这个问题。

我知道这是一个古老的话题,但我来到这里可能与OP相同的问题,看到人们如何继续误读它是令人沮丧的。或者也许我误读了它,我不知道。

粗略地说,字符串是计算机内存中的一个区域,在程序执行过程中,它包含可以映射到文本字符的字节序列。另一方面,字符串文字是一段尚未编译的源代码,它表示稍后在出现字符串的程序执行期间用于初始化字符串的值。

在C#中,语句…

 string query = "SELECT foo, bar"+ " FROM table"+ " WHERE id = 42";

不要产生一个三行字符串,但只有一行;三个字符串的串联(每个字符串从不同的文字初始化),其中没有一个包含新行修饰符。

OP似乎要问的——至少是我用这些词问的——不是如何在编译后的字符串中引入模仿源代码中发现的换行符,而是如何在源代码没有中为清晰起见分解一长串单行文本,在编译后的字符串中引入换行符。并且不需要延长执行时间,花在连接来自源代码的多个子字符串上。就像javascript或C++中的多行字符串文字中的尾随反斜杠。

建议使用逐字字符串,不要介意StringBuilderString.Join甚至带有字符串反转的嵌套函数等等,让我觉得人们并没有真正理解这个问题。或者我不明白。

据我所知,C#没有(至少在我仍在使用的旧石器时代版本中,从上一个十年开始)有一个功能可以干净地生成多行字符串文字,可以在编译而不是执行期间解决。

也许当前版本确实支持它,但我想我会分享我在字符串和字符串文字之间的差异。

更新:

(来自MeowCat2012的评论)可以的。OP的“+”方式是最好的。根据规范保证优化:http://stackoverflow.com/a/288802/9399618

您可以使用@""

        string sourse = @"{""items"":[{""itemId"":0,""name"":""item0""},{""itemId"":1,""name"":""item1""}]}";

是的,您可以将字符串拆分为多行,而无需将换行符引入实际字符串,但它并不漂亮:

string s = $@"This string{string.Empty} contains no newlines{string.Empty} even though it is spread onto{string.Empty} multiple lines.";

诀窍是引入计算结果为空的代码,并且该代码可能包含换行符而不影响输出。我将这种方法从这个答案调整到类似的问题。

对于这个问题显然有些混乱,但有两个提示,我们想要的是一个不包含任何换行符的字符串文字,其定义跨越多行。(在注释中,他这样说,“这就是我所拥有的”显示了不创建包含换行符的字符串的代码)

此单元测试显示了意图:

    [TestMethod]public void StringLiteralDoesNotContainSpaces(){string query = "hi"+ "there";Assert.AreEqual("hithere", query);}

更改上述查询定义,使其成为一个字符串文字,而不是两个字符串文字的串联,编译器可能会或可能不会优化为一个。

C++的方法是用反斜杠结束每行,导致换行符被转义而不会出现在输出中。不幸的是,第一行之后的每行必须保持对齐,以免在结果中添加额外的空格。

只有一种选择不依赖于可能不会发生的编译器优化,那就是将你的定义放在一行上。如果你想依赖编译器优化,你已经拥有的+很棒;你不必左对齐字符串,结果中不会出现换行符,而且这只是一个操作,没有函数调用,可以期待优化。

添加多行:使用@

string query = @"SELECT foo, barFROM tableWHERE id = 42";

将字符串值添加到中间:使用$

string text ="beer";string query = $"SELECT foo {text} bar ";

多行字符串将值添加到中间:使用$@

string text ="Customer";string query = $@"SELECT foo, barFROM {text}TableWHERE id = 42";

在C#11[2022]中,您将能够使用原始字符串文字。使用原始字符串文字可以更轻松地使用“字符,而无需编写转义序列。

OP的解决方案:

string query1 = """SELECT foo, barFROM tableWHERE id = 42""";
string query2 = """SELECT foo, barFROM tableWHERE id = 42and name = 'zoo'and type = 'oversized "jumbo" grand'""";

有关原始字符串文字的更多详细信息

有关详细信息,请参阅原始字符串文字 GitHub问题;和博客文章C#11预览更新-原始字符串文字、UTF-8等!