哪个字符串操作更好?

时间:2010-07-20 19:04:50

标签: c# .net

  

可能重复:
  String concatenation vs String Builder. Performance

以下两个选项之间的差异(性能和内存使用情况)?

选项1:

StringBuilder msgEntry = new StringBuilder();
msgEntry.AppendLine("<" + timeTag + ">" + timeStamp + "</" + timeTag + ">");

选项2:

StringBuilder msgEntry = new StringBuilder();
msgEntry.Append("<");
msgEntry.Append(timeTag);
msgEntry.Append(">");
msgEntry.Append(timeStamp);
msgEntry.Append("</");
msgEntry.Append(timeTag );
msgEntry.Append(">\n");

10 个答案:

答案 0 :(得分:27)

第二个是可能在内存使用方面略好一些,因为它不需要计算中间字符串 1 ...但它的可读性较差,IMO

就我个人而言:

msgEntry.AppendFormat("<{0}>{1}</{0}>", timeTag, timeStamp);

之后您没有显示您想要对StringBuilder做什么。如果您只想将其转换为字符串,那么我将使用:

string text = string.Format("<{0}>{1}</{0}>", timeTag, timeStamp);

开头。

表现如何?好吧,可能更糟 - 毕竟,它必须解析格式字符串。但除非你已经测量过并发现它是瓶颈,你为什么担心呢?

一般来说:

  • 确保您的架构合理有效 - 以后很难更改。
  • 在效率和简单性之间平衡您的内部设计,并强调可测试性;稍后更改设计可能需要一段时间,但通常应该没有兼容性问题。
  • 实现编写为尽可能可读。
  • 测量系统以确定它是否表现良好,以及瓶颈在哪里。他们几乎永远不会像这样代码。 (毕竟,我们不是在讨论循环中的字符串连接 。)
  • 当您找到瓶颈时,请尝试不同的优化并测量它们。不要认为你认为会更快的事情实际更快。

1 或传递给Concat的数组......我们不知道timeStamp的类型,所以我们无法确切知道那里发生了什么;在第二种形式中,它可以就地附加,而第一种形式可能需要将其打包并然后将其转换为字符串,然后再执行连接。

重新分配等的确切实现可能在.NET 3.5和.NET 4之间发生了变化(我知道实现的一些部分)。如果没有非常仔细的基准测试,我真的不愿意说哪个更快......但是可读性更容易调用,尽管是主观的。

答案 1 :(得分:3)

一般来说,StringBuilder ......但是当谈到性能时,唯一真正的测试是测量。特别是对于很多字符串更改,S​​tringBuilder绝对是最佳选择。对于几个字符串......使用+运算符附加它们可能更容易。

答案 2 :(得分:2)

我会使用.AppendFormat();在那种情况下

StringBuilder msgEntry = new StringBuilder();
msgEntry.AppendFormat("<{0}>{1}</{0}>", timeTag , timeStamp);

答案 3 :(得分:2)

就个人而言,我不会选择,并使用

msgEntry.AppendFormat("<{0}>{1}</{0}>", timeTag, timeStamp);

答案 4 :(得分:1)

如果您正在做的就是这样,请不要使用StringBuilder。由于可读性受到影响,开销过高。

试试这个:

string.Format("<{0}>{1}</{2}>", timeTag, timeStamp, timeTag);

答案 5 :(得分:1)

我依赖于MSDN的Performance Tips and Tricks in .NET Applications中的建议,该建议建议使用StringBuilder进行复杂字符串操作。

接下来建议:

  

权衡有一些开销   与创建一个相关联   StringBuilder对象,包括时间和内存。   在具有快速内存的计算机上,如果您正在执行大约五次操作,则StringBuilder变得值得。   根据经验,我会说10或   更多字符串操作是一个   任何开销的理由   机器,即使是较慢的机器。

我也会从代码优化中考虑这个建议.Net show:

  

特别重要的是   预先分配字符串的大小。   如果你不这样做,StringBuilder仍然是   更快,但如果你能预测的话   最终字符串的最终长度,   提前设定。

这是因为StringBuilder的默认容量是16.它会在超出容量时自动调整大小 - 每次都会翻倍。因此,如果您未设置初始容量,则可能会有几个不必要的限制。您可以计算示例中最大预期字符数,并初始化StringBuilder以使其不会调整大小。这将节省一些CPU。

这是some additional advice from MSDN

  

串联的表现   String或的操作   StringBuilder对象取决于方式   通常会发生内存分配。一个   字符串连接操作始终   分配内存,而a   StringBuilder连接操作   只有分配内存   StringBuilder对象缓冲区也是如此   小到容纳新数据。   因此,String类是   最好是串联   操作如果是固定数量的String   对象是连接的。在那里面   个案,个别串联   甚至可以将操作合并到一起   编译器的单个操作。一个   StringBuilder对象更适合   一个连接操作,如果一个   任意数量的字符串   级联;例如,如果一个循环   连接随机数   用户输入字符串。

答案 6 :(得分:0)

第二行更好,因为如果第一行中的stringbuilder有任何好处,你的收益就不会太多。但是对于像我这样的小字符串连接我不会打扰stringbuilder

答案 7 :(得分:0)

如果你打算做选项1,那么使用StringBuilder是没有意义的。你仍然在进行字符串连接,并最终会在内存中创建并丢弃多个额外的临时字符串。

对于类似的内容,您应该使用String.Format()

答案 8 :(得分:0)

第一个例子对我来说似乎不对。 在将字符串传递给StringBuilder之前连接字符串时,创建StringBuider对象有什么意义?

另请注意:

  • Append返回StringBuilder的实例,因此可以将对Append和AppendLine的调用链接在一起
  • 在第二个示例的末尾,您可以使用AppendLine(“&gt;”)而不是Append(“&gt; \ n”)
    StringBuilder msgEntry = new StringBuilder();
    msgEntry.Append("<")
        .Append(timeTag)
        .Append(">")
        .Append(timeStamp)
        .Append("</")
        .Append(timeTag )
        .AppendLine(">");

就我个人而言

    string.Format("<{0}>{1}</{0}>", timeTag, timeStamp);

除非您需要StringBuilder用于其他内容。

答案 9 :(得分:-1)

始终使用StringBuilder.Append()进行字符串连接。字符串+运算符会为每个新项目生成新的分配。