17

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

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

有类似的问题:

这个问题是在询问每种情况下会发生什么,这些示例的真正输出是什么?它们有什么区别?在这种情况下我应该在哪里使用它们?

4

10 回答 10

16

只要您不处理非常多(100+)的字符串或非常大的(长度> 10000)字符串,唯一的标准就是可读性。

对于这种规模的问题,请使用+. 为了便于阅读,+将该重载添加到字符串类中。

用于string.Format()更复杂的构图以及需要替换或格式化时。

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

于 2010-06-23T15:01:14.880 回答
8

从所有答案中收集信息,结果是这样的:

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

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

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

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

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

于 2010-06-23T18:06:03.087 回答
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 的意义,因为您已经在处理三个字符串文字。

我个人只在处理字符串数组时使用 Concat。

于 2010-06-23T16:03:05.923 回答
2

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

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

于 2010-06-23T15:34:55.060 回答
1

@Jerod Houghtelling答案

实际上 String.Format 在幕后使用 StringBuilder (如果需要,请在 String.Format 上使用反射)

我一般同意以下答案

于 2010-06-23T15:41:41.637 回答
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);
于 2010-06-23T17:11:10.597 回答
0

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

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

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

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

于 2010-06-24T05:19:54.257 回答
0

重要的是要记住字符串的行为不像常规对象。采取以下代码:

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

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

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

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

于 2010-08-09T08:31:38.080 回答
0

我看到没有人知道这种方法:

string Color = "red";
Console.WriteLine($"The apple is {Color}");
于 2021-09-25T11:05:19.523 回答
-1
var str3 = new StringBuilder
    .AppendFormat("abc{0}{1}", dynamicString, dynamicString2).ToString(); 

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

于 2010-06-23T16:43:01.697 回答