C#中的行继续字符

时间:2010-11-03 10:34:23

标签: c#

我们有一个包含很长字符串的变量的单元测试。

问题是如何在代码中编写它,而不会出现换行问题或代码难以阅读。

在VB中有一个行继续字符,在C#中是否存在等价物?

7 个答案:

答案 0 :(得分:55)

C#允许您将字符串拆分为多行,该术语称为verbatim literal

string myString = @"this is a
                    test
                   to see how long my string
                   can be



                    and it can be quite long";

如果您正在寻找VB中& _的替代方法,请使用+加入您的行。

答案 1 :(得分:48)

字符串常量

只需使用+运算符并将字符串分解为人类可读的行。编译器会发现字符串是常量的,并在编译时将它们连接起来。请参阅MSDN C#编程指南here

e.g。

const string myVeryLongString = 
    "This is the opening paragraph of my long string. " +
    "Which is split over multiple lines to improve code readability, " +
    "but is in fact, just one long string.";

IL_0003: ldstr "This is the opening paragraph of my long string. Which is split over multiple lines to improve code readability, but is in fact, just one long string."

字符串变量

请注意,当使用字符串插值将值替换为字符串时,$字符需要位于需要替换的每个行之前:

var interpolatedString = 
    "This line has no substitutions. " +
    $" This line uses {count} widgets, and " +
    $" {CountFoos()} foos were found.";

但是,对于string.Format的多次调用以及字符串的最终连接(标有***

,会产生负面效果后果
IL_002E:  ldstr       "This line has no substitutions. "
IL_0033:  ldstr       " This line uses {0} widgets, and "
IL_0038:  ldloc.0     // count
IL_0039:  box         System.Int32
IL_003E:  call        System.String.Format ***
IL_0043:  ldstr       " {0} foos were found."
IL_0048:  ldloc.1     // CountFoos
IL_0049:  callvirt    System.Func<System.Int32>.Invoke
IL_004E:  box         System.Int32
IL_0053:  call        System.String.Format ***
IL_0058:  call        System.String.Concat ***

虽然您可以使用$@来提供单个字符串并避免性能问题,unless the whitespace is placed inside {}(看起来很奇怪,IMO),这与Neil Knight的回答有同样的问题,因为它会包括行分类中的任何空格:

var interpolatedString = $@"When breaking up strings with `@` it introduces
    <- [newLine and whitespace here!] each time I break the string.
    <- [More whitespace] {CountFoos()} foos were found.";

注入的空白很容易发现:

IL_002E:  ldstr       "When breaking up strings with `@` it introduces
    <- [newLine and whitespace here!] each time I break the string.
    <- [More whitespace] {0} foos were found."

另一种方法是恢复为string.Format。根据我的初始答案,格式化字符串是一个常量:

const string longFormatString = 
    "This is the opening paragraph of my long string with {0} chars. " +
    "Which is split over multiple lines to improve code readability, " +
    "but is in fact, just one long string with {1} widgets.";

然后进行评估:

string.Format(longFormatString, longFormatString.Length, CountWidgets());

然而,鉴于格式化字符串和替换标记之间可能存在分离,这仍然很难维护。

答案 2 :(得分:6)

@"string here
that is long you mean"

但要小心,因为

@"string here
           and space before this text
     means the space is also a part of the string"

它也会转义字符串中的内容

@"c:\\folder" // c:\\folder
@"c:\folder" // c:\folder
"c:\\folder" // c:\folder

相关

答案 3 :(得分:5)

您可以使用逐字文字:

const string test = @"Test
123
456
";

但是第一行的缩进很棘手/丑陋。

答案 4 :(得分:0)

您必须使用以下方式之一:

    string s = @"loooooooooooooooooooooooong loooooong
                  long long long";

string s = "loooooooooong loooong" +
           " long long" ;

答案 5 :(得分:0)

StuartLC在出色的回答中引用了an answer的一个相关问题,并提到在插值字符串的{expression}内放置换行符“看起来很奇怪”。大多数人都同意,但是使用专用的{expression}块可以解析为default(String),即null,可以在某种程度上减轻不愉快的源代码效应,并且不会造成任何运行时后果(尤其是 not String.Empty)。

(尽管是次要的)要点是不要弄乱或污染您的实际表达式内容,而是为此目的使用专用令牌。因此,如果您声明一个常量,例如:

const String more = null;

...然后一行可能太长而无法在源代码中查看,例如...

var s1 = $"one: {99 + 1} two: {99 + 2} three: {99 + 3} four: {99 + 4} five: {99 + 5} six: {99 + 6}";

...可以这样写。

var s2 = $@"{
    more}one: {99 + 1} {
    more}two: {99 + 2} {
    more}three: {99 + 3} {
    more}four: {99 + 4} {
    more}five: {99 + 5} {
    more}six: {99 + 6}";

或者也许您更喜欢同一事物的不同“奇数”布局:

var s3 = $@"{more
    }one: {99 + 1} {more
    }two: {99 + 2} {more
    }three: {99 + 3} {more
    }four: {99 + 4} {more
    }five: {99 + 5} {more
    }six: {99 + 6}";

所有三个示例在运行时都产生相同的string,在这种情况下,它们全部在一行上:

  

one: 100 two: 101 three: 102 four: 103 five: 104 six: 105

正如Stuart所建议的,在这两个示例中都通过不使用+来连接字符串来保持IL性能。尽管在我的新示例中,较长的格式字符串确实存储在IL中,并因此存储在可执行文件中,但它所引用的空占位符并未初始化,并且在运行时没有多余的串联或函数调用。为了进行比较,下面是上述两个示例的IL。

第一个示例的IL

ldstr "one: {0} two: {1} three: {2} four: {3} five: {4} six: {5}"
ldc.i4.6
newarr object
dup
ldc.i4.0
ldc.i4.s 100
box int32
stelem.ref
dup
ldc.i4.1
ldc.i4.s 101
box int32
stelem.ref
dup
ldc.i4.2
ldc.i4.s 102
box int32
stelem.ref
dup
ldc.i4.3
ldc.i4.s 103
box int32
stelem.ref
dup
ldc.i4.4
ldc.i4.s 104
box int32
stelem.ref
dup
ldc.i4.5
ldc.i4.s 105
box int32
stelem.ref
call string string::Format(string, object[])

第二个示例为IL

ldstr "{0}one: {1} {2}two: {3} {4}three: {5} {6}four: {7} {8}five: {9} {10}six: {11}"
ldc.i4.s 12
newarr object
dup
ldc.i4.1
ldc.i4.s 100
box int32
stelem.ref
dup
ldc.i4.3
ldc.i4.s 101
box int32
stelem.ref
dup
ldc.i4.5
ldc.i4.s 102
box int32
stelem.ref
dup
ldc.i4.7
ldc.i4.s 103
box int32
stelem.ref
dup
ldc.i4.s 9
ldc.i4.s 104
box int32
stelem.ref
dup
ldc.i4.s 11
ldc.i4.s 105
box int32
stelem.ref
call string string::Format(string, object[])

答案 6 :(得分:-1)

如果您声明了不同的变量,请使用以下简单方法:

Int salary=2000;

String abc="I Love Pakistan";

Double pi=3.14;

Console.Writeline=salary+"/n"+abc+"/n"+pi;
Console.readkey();