C#6中的长字符串插值行

161

我发现字符串插值在应用于我现有代码库的字符串格式调用时非常好用,但考虑到通常首选的列限制,当被插值的表达式较为复杂时,该字符串很快就会变得过长而不适合一行。使用格式化字符串时,您可以将要格式化的变量列表拆分成多行。

var str = string.Format("some text {0} more text {1}",
    obj1.property,
    obj2.property);

有人有喜欢的方法来分割这些行吗?

我想你可以做类似这样的事情:

var str = $"some text { obj1.property }" +
  $" more text { obj2.property };

1
根据我的经验,最好避免插入复杂表达式。在这种情况下,最好提取一个变量。如果你这样做,并且在字符串内部分割出换行符,通常会很好地适配。 - markijbema
2
我对这个问题感到困惑。我只是想要一个像@""一样工作的多行 $"" - Colonel Panic
3
上校恐慌,这个问题是关于如何分割长的插值行,以避免违反列宽要求,而不在字符串字面量本身引入换行符。 $@"" 很好用,但是任何引入到其中的换行都将在字符串字面量中。 - Jeremiah Gowdy
1
要支持 $@ 中的 \t\r\n,请参见以下问题:https://stackoverflow.com/questions/51991713/long-string-interpolation-lines-in-c6-dont-support-tab-cr-and-lf/51991855#51991855 - M.Hassan
实际上,即使 $"a: {a}" + $"b: {b}" 产生了一个简单的字符串,也防止我在多行上打破字符串插值。 https://dev59.com/SVQJ5IYBdhLWcg3w66jM 也得到了这个答案。 - hsandt
请查看 C# 11 原始字符串字面值,网址为 https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#raw-string-literals。 - Artur INTECH
5个回答

233

你可以将一行代码分成多行,但是这样语法看起来不太好看了。

要使用插值的字面字符串,你需要使用$@语法,并且你可以在{...}参数中放置换行符,就像这样:

string s = $@"This is all {
    10
    } going to be one long {
    DateTime.Now
    } line.";

上面的字符串不会包含任何换行符,并且实际上会包含以下内容:

这将是一行很长的内容,不会有任何换行符01.08.2015 23.49.47。

(注意,这是挪威格式)

然而,我并不建议停止使用 string.Format。在我看来,一些字符串插值表达式看起来非常好,但是更复杂的表达式开始变得非常难以阅读。考虑到除非您使用 FormattableString,否则代码最终还是会编译成对 String.Format 的调用,因此我认为在有意义的地方继续使用 String.Format


1
很不错的答案。我非常确定FormattableString也会归结为对String.Format的调用。 - Alex Booker
9
这个答案帮助我找到了如何做与此完全相反的事情。感谢$@""语法! - Bobson
1
@AlexBooker,这个问题比较复杂。你不能使用FormattableString.Invarian($"Hello {name}" + \n "are you the owner of {pet}?");,因为它会将两个插值字符串合并成一个简单的字符串。 - ANeves
插值的逐字字符串会保留换行符和制表符。将以下内容输入到 C# 交互窗口中,结果字符串将被格式化:> var name = "Simon"; var templateName = "How to interpolate a verbatim string"; var now = DateTime.UtcNow;. var output = $@"Hi {name}, This template is a demo of {templateName}. It was ran at {now.ToString("o")}"; > output输出结果为 "Hi Simon,\r\nThis template is a demo of How to interpolate a verbatim string.\r\n\r\nIt was ran at 2020-01-24T15:49:35.6678353Z" - Enzoaeneas
2
@Enzoaeneas 我认为你高估了注释中的格式支持,但我理解并同意你的观点。 - Lasse V. Karlsen
现在,话虽如此,我不会停止使用string.Format。可惜的是,想要进行多行字符串插值的动机与为什么不喜欢使用string.Format是一样的,即内容越长,从上下文中删除变量就越成问题。C#团队引入这种空格依赖性到字符串插值中,设计相当糟糕。 - Paul Childs

68

你可以将$@组合在一起,以获得字符串插值和多行字符串字面量:

var str = $@"some text { obj1.property }
     more text { obj2.property }";

但是这会在它们之间添加一个NewLine字符,因此这可能不是你想要的。


3
@实际上会将换行符放入文字字面值中吗? - Jeremiah Gowdy
5
明白了,我已经将回答进行了更新,明确地表达了这一点。 - MarcinJuraszek
3
不仅是新的一行,而且也包括新一行开头的制表符。为了在Visual Studio中正确地呈现使用"$@"时的实际字符串格式,您必须从文本编辑器的最左边开始每一行新的内容。 - GDS
使用此解决方案时,您无法在字符串中使用例如 \r 和 \n。 - Johan Franzén

28

尽管OP要求其他的东西,但我相信许多人看到这个问题会希望有一个像@""一样工作的多行内插字符串$""。为了实现这一点,请使用$@""

$@"Height: {height}
Width: {width}
Background: {background}"

5
他不希望输出结果有换行符,只希望代码本身可以自动换行到不同的行。 - Martin Capodici
9
他明确表示,这个答案是为那些使用字符串插值语法寻找如何创建多行字符串的观众而准备的。 - Brandon Bonds

4

This is it:

var str = $"some text { obj1.property }" +
          $" more text { obj2.property }";

请注意 $"..." + $"..." 中第二个 $

23
请注意,这将调用两次String.Format并在内存中创建三个字符串(Side A、Side B和A+B)。 - Kevin Kalitowski
2
这样做不会阻止您在连接的字符串上使用 FormattableString 强制转换吗? - binki
4
在许多现今的实现中,运行于拥有千兆赫处理器和数千兆字节内存的计算机上,多调用一次函数和额外增加一个字符串不会导致性能问题。性能问题通常由O(n2)等复杂度算法引起。我认为,对这个人进行贬低评分是不公平的。 - Johan Franzén

0

我已经使用了StringBuilder在重写的ToString()方法中作为一个例子。

    // return employee data
    public override string ToString()
    {
        StringBuilder buffer = new StringBuilder();
        buffer.AppendLine($"Number: {EmployeeNumber}");
        buffer.AppendLine($"Name: {EmployeeName}");
        buffer.AppendLine($"Address: {PostalAddress}");
        buffer.AppendLine($"Phone: {PhoneNumber}");
        buffer.AppendLine($"Age: {EmployeeAge}");
        buffer.AppendLine($"Gender: {EmployeeGender}");
        buffer.AppendLine($"Status: {EmployeeStatus}");
        buffer.AppendLine($"Manager: {EmployeeManager}");
        buffer.AppendLine($"Start: {EmployeeStartDate.ToShortDateString()}");
        return buffer.ToString();
    }

那为什么不使用 buffer.AppendFormat("{0}Number: {1}", Environment.NewLine, EmployeeNumber); 呢? - T.S.
1
如果这样做很频繁,性能会很差。您正在每行执行插值,然后将其添加到字符串构建器中。最好只需进行多个附加调用,并在下一个项目的开始之前添加新行字符。您当前的方式会为每个字符串和插值结果使用内存,需要进行垃圾回收。 - Kevin Green

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接