由于我认为这里的答案并不能涵盖所有内容,因此我想在这里做一点补充。
Console.WriteLine(string format, params object[] pars)
来电string.Format
。'+' 表示字符串连接。我不认为这总是与风格有关。我倾向于根据我所处的环境混合这两种风格。
简短的回答
您面临的决定与字符串分配有关。我会尽量让它简单。
说你有
string s = a + "foo" + b;
如果执行此操作,它将评估如下:
string tmp1 = a;
string tmp2 = "foo"
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);
tmp
这里并不是一个真正的局部变量,但它是 JIT 的临时变量(它被推送到 IL 堆栈上)。如果您将字符串压入堆栈(例如ldstr
在 IL 中用于文字),您会将对字符串指针的引用放在堆栈上。
您调用此引用的那一刻concat
成为一个问题,因为没有任何包含两个字符串的可用字符串引用。这意味着 .NET 需要分配一个新的内存块,然后用两个字符串填充它。这是一个问题的原因是分配相对昂贵。
这将问题更改为:如何减少concat
操作次数?
所以,粗略的答案是:string.Format
对于 >1 个 concat,'+' 对于 1 个 concat 就可以了。而且,如果您不关心进行微性能优化,string.Format
那么在一般情况下就可以正常工作。
关于文化的注释
还有一种叫做文化的东西...
string.Format
使您可以CultureInfo
在格式中使用。一个简单的运算符“+”使用当前文化。
如果您正在编写文件格式和 f.ex,这一点尤其重要。double
您“添加”到字符串的值。在不同的机器上,如果您不使用string.Format
显式的CultureInfo
.
前任 考虑一下如果你改变一个 '.' 会发生什么。对于“,”,在编写逗号分隔值文件时......在荷兰语中,小数点分隔符是逗号,因此您的用户可能会得到一个“有趣”的惊喜。
更详细的回答
如果您事先不知道字符串的确切大小,最好使用这样的策略来过度分配您使用的缓冲区。松弛空间首先被填充,然后数据被复制进来。
增长意味着分配一个新的内存块并将旧数据复制到新缓冲区。然后可以释放旧的内存块。此时你得到了底线:增长是一项昂贵的操作。
最实用的方法是使用过度分配策略。最常见的策略是以 2 的幂来过度分配缓冲区。当然,您必须做得比这更聪明(因为如果您已经知道需要 128,那么从 1、2、4、8 增长是没有意义的字符),但你得到了图片。该策略确保您不需要我上面描述的太多昂贵的操作。
StringBuilder
是一个基本上以 2 的幂为基础过度分配底层缓冲区的类。在引擎盖下string.Format
使用。StringBuilder
这使您的决定成为过度分配和追加(-multiple)(w/wo 文化)或只是分配和追加之间的基本权衡。