我该如何连接字符串?

时间:2010-06-23 14:59:25

标签: c# .net string string-concatenation

这些例子之间是否存在差异?我应该在哪种情况下使用哪个?

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);

有类似的问题:

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

9 个答案:

答案 0 :(得分:16)

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

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

使用string.Format()表示更复杂的作品以及需要替换或格式化时。

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

答案 1 :(得分:8)

从所有答案中收集信息,结果表明行为如下:

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

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

String.FormatStringBuilder..(示例3)相同,只是String.Format执行params验证并使用参数的长度实例化内部StringBuilder

当需要格式字符串时,应使用

String.Format,并连接简单的字符串。

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

StringBuilder

答案 2 :(得分:5)

在您的方案中使用+运算符。

当你在字符串中混合使用变量和静态数据时,我只会使用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。

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

@ Jerod Houghtelling Answer

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

我同意以下answer一般

答案 5 :(得分:1)

@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);

答案 6 :(得分:0)

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

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

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

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

答案 7 :(得分:0)

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

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

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

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

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

答案 8 :(得分:-1)

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

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