C# 使用+;=一串

C# 使用+;=一串,c#,C#,正如标题所示,我有没有理由不在字符串的末尾添加以下内容: string someString = "test"; someString += "Test"; 如果只做一次,那没什么大不了的。获取两个字符串的内容,创建一个新字符串并将其分配给someString。如果您多次执行上述操作(例如,在循环中),则会出现问题。对于每次执行,您都在堆中分配一个新对象,即一个新的字符串实例。这就是为什么如果必须多次将内容附加到字符串中,最好使用基于缓冲区的类型,例如StringBuilder。如果只执行一次

正如标题所示,我有没有理由不在字符串的末尾添加以下内容:

string someString = "test";
someString += "Test";

如果只做一次,那没什么大不了的。获取两个字符串的内容,创建一个新字符串并将其分配给
someString
。如果您多次执行上述操作(例如,在循环中),则会出现问题。对于每次执行,您都在堆中分配一个新对象,即一个新的字符串实例。这就是为什么如果必须多次将内容附加到字符串中,最好使用基于缓冲区的类型,例如
StringBuilder

如果只执行一次,那没什么大不了的。获取两个字符串的内容,创建一个新字符串并将其分配给
someString
。如果您多次执行上述操作(例如,在循环中),则会出现问题。对于每次执行,您都在堆中分配一个新对象,即一个新的字符串实例。这就是为什么如果必须多次将内容附加到字符串中,最好使用基于缓冲区的类型,例如
StringBuilder

您的方法可以很好地工作。您可以使用StringBuilder作为替代

var sb = new StringBuilder();
sb.Append("Foo");
sb.Append(" - ");
sb.Append("Bar"); 

string someString = sb.ToString();

你的方法会奏效的。您可以使用StringBuilder作为替代

var sb = new StringBuilder();
sb.Append("Foo");
sb.Append(" - ");
sb.Append("Bar"); 

string someString = sb.ToString();

如果您执行以下操作:

var s = "abc";
s += "def";
s += "ghi";
(或多或少)在第2行,当创建新字符串时,
abc
的内容被复制到其中,然后
def
的内容被复制到其中,然后这个新字符串(
abcdef
)被分配给变量

然后在第3行,创建另一个新字符串,将变量先前值(
abcdef
)的内容复制到该字符串中,然后将结果分配给变量


如果重复执行此操作,可以看到字符串的开头在每次
+=
操作中都会被一次又一次地复制。在构建长字符串的循环中,这可能会产生影响。这可以通过使用或
列表
进行优化,以便您只复制最终结果的每一部分一次(或一些与循环迭代次数无关的其他常量)。

如果您执行以下操作:

var s = "abc";
s += "def";
s += "ghi";
(或多或少)在第2行,当创建新字符串时,
abc
的内容被复制到其中,然后
def
的内容被复制到其中,然后这个新字符串(
abcdef
)被分配给变量

然后在第3行,创建另一个新字符串,将变量先前值(
abcdef
)的内容复制到该字符串中,然后将结果分配给变量


如果重复执行此操作,可以看到字符串的开头在每次
+=
操作中都会被一次又一次地复制。在构建长字符串的循环中,这可能会产生影响。这可以通过使用或
列表
进行优化,这样您只需复制最终结果的每一部分一次(或其他一些与循环迭代次数无关的常量)。

对于“更长”字符串或“多次”,它可以做“远远超出所需的工作”。在这些情况下,请参见
StringBuilder
。(我发现使用案例非常罕见,并且更喜欢普通的字符串连接或其他形式的流。)检查一下:我不使用上述方法的唯一原因是性能原因,因为有非常大的stings,否则用这种方法连接是很好的。有关与StringBuilder的比较,请参阅(和类似内容)。有关“更长”字符串或“很多时候”它可以做“比需要的工作多得多”。在这些情况下,请参阅
StringBuilder
(我发现这些用例非常罕见,并且更喜欢普通的字符串连接或其他形式的流式处理。)检查一下:我不使用上述方法的唯一原因是出于性能方面的考虑,因为有非常大的stings,否则我认为用这种方法进行连接是很好的。请参阅(和类似内容)以与StringBuilder进行比较。并执行1000次(在“大小合理”的字符串上)通常情况下仍然没有什么大不了的..97/3;也就是说,我只在我确定这是一个问题的特定情况下使用
StringBuilder
。@Eve是的。这在正常的.NET程序中是应该的。分代GC得到了极大的优化(事实上,这是整个方法的要点)非常有效地处理这个问题。+1。@millimoose,GC很快就完成了它的工作,但它仍然比根本不做任何工作慢。如果代码看起来差不多,我看不出有任何理由明确避免使用
StringBuilder
(或潜在的流/编写器类)“EVE”复制更可能是一个问题,尤其是如果组件字符串的数量和长度都是很大的。例如,考虑一个情况,其中每个字符串连接了100个字符串,每个字符有10个字符,在每一个10个字符串分配之后,GC都在其中,其中对象句柄有8个字节。GC只需要检查10个字符串R。引用是最年轻的一代(80字节)。但是,在循环快结束时,每次迭代都要复制近1000个字符(2000字节)。@Eve我的观点不是GC压力不存在,而是它不随字符串的长度扩展(与复制成本不同),因此它不会成为使用
string.Concat()
会导致的任何减速的主要原因。此外,如果您在代码中使用LINQ,那么谈论GC压力(就像大多数人一样)这太疯狂了,试图盲目地对对象分配进行微优化听上去像是错过了一片森林。而且做1000次(在“大小合理”的字符串上)通常也没什么大不了的。97/3;也就是说,我只在我确定这是一个问题的特定情况下使用
StringBuilder
。(模板生成器中可能有一个示例。)@