我该如何连接字符串?
这些例子之间有区别吗? 我应该在哪种情况下使用哪个?
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.Format
与StringBuilder..
相同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();
上面的代码是最快的。 所以如果你想要它快速使用。 如果你不在乎,可以使用其他任何东西。