我该如何连接字符串?

这些例子之间有区别吗? 我应该在哪种情况下使用哪个?

var str1 = "abc" + dynamicString + dynamicString2; var str2 = String.Format("abc{0}{1}", dynamicString, dynamicString2); var str3 = new StringBuilder("abc"). Append(dynamicString). Append(dynamicString2). ToString(); var str4 = String.Concat("abc", dynamicString, dynamicString2); 

有类似的问题:

  • 字符串连接的差异只询问+运算符,并且在答案中甚至没有提到它被转换为String.Concat
  • 什么是最好的字符串连接方法 ,它与我的问题没有真正关系,它要求最好的,而不是对串联字符串及其输出的可能方法的比较,正如这个问题所做的那样。

这个问题是询问每种情况会发生什么,这些例子的实际输出是什么? 他们有什么不同? 在哪种情况下我应该在哪里使用它们?

只要你没有使用很多(100+)字符串或非常大(长度> 10000)的字符串,唯一的标准就是可读性。

对于此大小的问题,请使用+ 。 为了便于阅读,将+重载添加到字符串类中。

对于更复杂的合成以及需要替换或格式化时,请使用string.Format()

组合多个(数百个或更多)或非常大的部分(长度>> 1000)时使用StringBuilder 。 StringBuilder没有可读性function,只是为了提高性能。

收集所有答案中的信息后,结果如下:

+运算符与String.Concat相同,可用于循环外的小连接,可用于小任务。

在编译时, +运算符生成单个字符串(如果它们是静态的),而String.Concat生成表达式str = str1 + str2; 即使它们是静止的。

String.FormatStringBuilder..相同StringBuilder.. (示例3),除了String.Format对params进行validation并使用参数的长度实例化内部StringBuilder

当需要格式字符串时,应使用String.Format ,并连接简单的字符串。

当您需要连接大字符串或循环时,应该使用StringBuilder

在场景中使用+运算符。

当你在字符串中混合使用变量和静态数据时,我只会使用String.Format()方法。 例如:

 string result=String.Format( "Today {0} scored {1} {2} and {3} points against {4}",..); //looks nicer than string result = "Today " + playerName + " scored " + goalCount + " " + scoreType + " and " + pointCount + " against " + opposingTeam; 

我没有看到使用StringBuilder的意义,因为你已经处理了三个字符串文字。

我个人在处理String数组时只使用Concat。

我的经验法则是使用String.Format如果你正在进行相对少量的连接(<100)和StringBuilder ,那么连接将会很大或者可能会很大。 如果我有一个数组并且不需要任何格式化,我使用String.Join

如果你有一个可枚举的集合,你也可以在LINQ中使用Aggregate函数: http : //msdn.microsoft.com/en-us/library/bb548651.aspx

@ Jerod Houghtelling 答案

实际上String.Format在后台使用StringBuilder(如果需要,可以在String.Format上使用reflecton)

我一般同意以下答案

@Xander。 我相信你是男人。 但是我的代码显示sb比string.format快。

打败这个:

 Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10000; i++) { string r = string.Format("ABC{0}{1}{2}", i, i-10, "dasdkadlkdjakdljadlkjdlkadjalkdj"); } sw.Stop(); Console.WriteLine("string.format: " + sw.ElapsedTicks); sw.Reset(); sw.Start(); for (int i = 0; i < 10000; i++) { StringBuilder sb = new StringBuilder(); string r = sb.AppendFormat("ABC{0}{1}{2}", i, i - 10, "dasdkadlkdjakdljadlkjdlkadjalkdj").ToString(); } sw.Stop(); Console.WriteLine("AppendFormat: " + sw.ElapsedTicks); 

重要的是要理解字符串是不可变的,它们不会改变。 因此,任何时候你改变,添加,修改或任何字符串 – 它将在内存中创建一个新的“版本”字符串,然后将旧版本用于垃圾收集。 所以这样的事情:

 string output = firstName.ToUpper().ToLower() + "test"; 

这将创建一个字符串(用于输出),然后在内存中创建三个其他字符串(一个用于:ToUpper(),ToLower()的输出,然后一个用于连接“test”)。

因此,除非您使用StringBuilder或string.Format,否则您执行的任何操作都将在内存中创建字符串的额外实例。 这当然是一个循环内部的问题,你最终可能会有数百或数千个额外的字符串。 希望有所帮助

重要的是要记住字符串的行为不像常规的objets。 请使用以下代码:

 string s3 = "Hello "; string s3 += "World"; 

这段代码将在堆上创建一个新字符串并将“Hello”放入其中。 然后,堆栈上的字符串对象将指向它(就像常规对象一样)。

然后,第2行将在堆“Hello World”上创建第二个字符串,并将堆栈上的对象指向它。 初始堆栈分配仍然存在,直到调用垃圾收集器。

所以….如果你在调用垃圾收集器之前加载了这些调用,你可能会浪费大量内存。

 var str3 = new StringBuilder .AppendFormat("abc{0}{1}", dynamicString, dynamicString2).ToString(); 

上面的代码是最快的。 所以如果你想要它快速使用。 如果你不在乎,可以使用其他任何东西。