C#中的多行字符串文字

Che*_*het 962 c# string shorthand

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

这就是我现在拥有的:

string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
Run Code Online (Sandbox Code Playgroud)

我知道PHP有

<<<BLOCK

BLOCK;
Run Code Online (Sandbox Code Playgroud)

C#有类似的东西吗?

Joh*_*sch 1476

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

string query = @"SELECT foo, bar
FROM table
WHERE id = 42";
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你的字符串包含双引号("),你可以像这样转义它们:""(那是两个双引号字符) (79认同)
  • 无论如何,这是一个字符串文字 - 它是带有@符号的*verbatim*字符串文字. (39认同)
  • 有没有办法在不创建新行的情况下完成上述操作?我有一段很长的文本,我希望看到它包含在IDE中,而不必使用加号("hi"+"there"). (8认同)
  • @afsharm你可以使用$ @"text" (7认同)
  • @noelicus - 不是真的,但你可以通过使用上面的weiqure技术来解决这个问题:`@"my string".Replace(Environment.NewLine,"")` (2认同)
  • `@` 和新的 C# 运算符 `$` 的组合怎么样? (2认同)
  • 这个答案是不正确的。您的查询字符串最终包含换行符,这不是所要求的。我相信正确的答案是“不,你不能在 C# 中做到这一点”。请参阅Carco Loco 的回答。我承认你有点不清楚他想要一个“多行字符串文字”是什么意思,但他的“这就是我现在拥有的”应该消除对他的意图的任何怀疑。 (2认同)

Jon*_*eet 528

它在C#中被称为逐字字符串文字,它只是在文字之前放置@的问题.这不仅允许多行,而且还会关闭转义.例如,您可以这样做:

string query = @"SELECT foo, bar
FROM table
WHERE name = 'a\b'";
Run Code Online (Sandbox Code Playgroud)

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

string quote = @"Jon said, ""This will work,"" - and it did!";
Run Code Online (Sandbox Code Playgroud)

  • @TamaMcGlinn:我会在答案中添加一些内容 - OP 何时写下这个问题尚不清楚。 (6认同)
  • 这个答案是错误的;它引入了 OP 不希望的换行符。 (4认同)

Mar*_*rke 103

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

// this would give a format exception
string.Format(@"<script> function test(x) 
      { return x * {0} } </script>", aMagicValue)
// this contrived example would work
string.Format(@"<script> function test(x) 
      {{ return x * {0} }} </script>", aMagicValue)
Run Code Online (Sandbox Code Playgroud)

  • 它有什么不同?有或没有"@"你必须加倍"{{"得到"{"作为可打印字符,它是String.Format的问题,而不是字符串内容. (14认同)
  • 对于想要将Javascript代码放在字符串中的人来说,这是一个值得注意的问题,这可能在逐字字符串文字中比常规字符串更常用. (12认同)
  • 在新的C#6.0中,您可以将索引属性运算符与逐字字符串文字一起使用(例如$ $"Value is {this.Value}";) (2认同)
  • @Heliac我认为您的意思是,内插字符串也可以使用该语法来表示文字。var query = $ @“从表中选择foo,bar,其中id = {id}”; (2认同)

dav*_*v_i 96

我发现使用字符串文字的问题是它可以使你的代码看起来有点" 怪异 ",因为为了不在字符串本身中获取空格,它必须完全左对齐:

    var someString = @"The
quick
brown
fox...";
Run Code Online (Sandbox Code Playgroud)

呸.

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

var someString = String.Join(
    Environment.NewLine,
    "The",
    "quick",
    "brown",
    "fox...");
Run Code Online (Sandbox Code Playgroud)

当然,如果你只是想在逻辑上分割的SQL语句的线条像你和实际上并不需要一个新行,你永远可以替代Environment.NewLine" ".

  • 虽然丑陋,但第一个版本*不需要运行代码*.第二个选项显然有连接单独字符串的运行时开销. (4认同)
  • 更清洁,谢谢.此外,String.Concat的工作方式类似,不需要分隔符. (2认同)

Hel*_*iac 91

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

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

  • 很酷,直到现在我才知道这件事.如果有人有兴趣:$ thingy被称为"Interpolated Strings",你可以在这里详细阅读:https://msdn.microsoft.com/en-us/library/dn961160.aspx (10认同)
  • 我假设文字花括号必须加倍,例如`$@"{{example literal text { fooString }.}}"` 这可能会混淆一些人,因为 Angular、React 和 Vue.js 使用相反的约定。 (2认同)

Car*_*oco 46

为什么人们会将字符串与字符串文字混淆?接受的答案是对不同问题的一个很好的答案; 不是这个.

我知道这是一个古老的话题,但我来到这里可能和OP一样,并且看到人们如何误读它是令人沮丧的.或许我误解了它,我不知道.

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

在C#中,声明......

 string query = "SELECT foo, bar"
 + " FROM table"
 + " WHERE id = 42";
Run Code Online (Sandbox Code Playgroud)

...... 不会产生三线串而是一根线; 三个字符串的串联(每个字符串从不同的字面值初始化),其中没有一个字符串包含换行符.

OP似乎要问的是 - 至少我会问这些话 - 不是如何在编译的字符串中引入模仿源代码中找到的换行符,而是如何分解清晰度很长,源代码中的单行文本,不会在编译的字符串中引入中断.并且不需要延长执行时间,花费加入来自源代码的多个子串.就像javascript或C++中多行字符串文字中的尾部反斜杠一样.

建议使用逐字字符串,请不要介意的StringBuilderS,String.Join用绳子逆转并没有什么,让我觉得人不是真正理解这个问题s甚至嵌套函数.或许我不明白.

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

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

  • 有些人(包括我自己)在查看原始问题时可能会感到困惑,因为here-doc格式(shell、php、perl...)包含换行符。因此,如果OP与PHP的heredoc进行比较,那么包含换行符应该不是问题。 (3认同)
  • 你可以。OP的“+”方法是最好的。根据规范,保证优化:/sf/answers/20216171/ 不过,您仍然是少数理解这个问题的人之一。是否可以删除或折叠可能具有误导性但已接受的答案? (3认同)
  • 感谢您的提示,@MeowCat2012。看了一些反编译的代码,似乎确实是这样。 (2认同)

Tod*_*odd 38

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

\n

OP的解决方案:

\n
string query1 = """\n    SELECT foo, bar\n    FROM table\n    WHERE id = 42\n    """;\n\nstring query2 = """\n    SELECT foo, bar\n    FROM table\n    WHERE id = 42\n    and name = \'zoo\'\n    and type = \'oversized "jumbo" grand\'\n    """;\n
Run Code Online (Sandbox Code Playgroud)\n
\n

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

\n

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

\n


Isa*_*ala 23

添加多行:使用@

string query = @"SELECT foo, bar
FROM table
WHERE id = 42";
Run Code Online (Sandbox Code Playgroud)

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

string text ="beer";
string query = $"SELECT foo {text} bar ";
Run Code Online (Sandbox Code Playgroud)

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

string text ="Customer";
string query = $@"SELECT foo, bar
FROM {text}Table
WHERE id = 42";
Run Code Online (Sandbox Code Playgroud)


小智 10

我没有看到这个,所以我会在这里发布它(如果你有兴趣传递一个字符串,你也可以这样做.)这个想法是你可以在多行上打破字符串并添加你自己的内容(也在多条线上)以任何你想要的方式.这里"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
                                )";
    }
Run Code Online (Sandbox Code Playgroud)

  • 非常危险我会说:很容易让某人以这种方式进行SQL注入. (8认同)
  • 只要你知道你的查询字符串中的所有变量(如果有的话)都来自代码常量或其他安全源 - 例如,`createTable("MyTable");它无论如何,OP的问题是关于它的问题.如何直接在代码中输入多行字符串文字,而不是如何构建数据库查询本身.:) (4认同)
  • 应该使用字符串构建器,特别是如果加号(+)的数量很多. (2认同)

Tam*_*inn 8

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

string s = $@"This string{
string.Empty} contains no newlines{
string.Empty} even though it is spread onto{
string.Empty} multiple lines.";
Run Code Online (Sandbox Code Playgroud)

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

对于问题是什么显然存在一些困惑,但是有两个提示表明我们在这里想要的是一个不包含任何换行符的字符串文字,其定义跨越多行。(在评论中他是这么说的,“这就是我所拥有的”显示的代码不会创建带有换行符的字符串)

此单元测试显示了意图:

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

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

C++ 方法是以反斜杠结束每一行,从而导致换行符被转义并且不会出现在输出中。不幸的是,仍然存在这样的问题:第一行之后的每一行必须左对齐,以免在结果中添加额外的空格。

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


vov*_*kas 7

您可以使用@“”

        string sourse = @"{
        ""items"":[
        {
            ""itemId"":0,
            ""name"":""item0""
        },
        {
            ""itemId"":1,
            ""name"":""item1""
        }
        ]
    }";
Run Code Online (Sandbox Code Playgroud)

  • 您应该解释每个命令的作用,因为@表示逐字字符串,而“”表示转义双引号。 (2认同)

der*_*ugo 7

除了Kind Contributor 关于原始字符串文字的回答之外

您现在还可以将其与字符串插值结合起来!

请参阅原始字符串文字

var someValue = 23.45f;
    
var json = $$"""
           {
               "summary": "text",
               "value" : {{someValue}},
           };
           """;
                   
Console.WriteLine(json);
Run Code Online (Sandbox Code Playgroud)

将导致

{
    "summary": "text",
    "value" : 23.45,
};
Run Code Online (Sandbox Code Playgroud)

小提琴