何时使用StringBuilder.AppendLine/String.Format和StringBuilder.AppendFormat?

60
最近有一个问题涉及使用String.Format()。我回答的一部分包括建议使用StringBuilder.AppendLine(string.Format(...))。Jon Skeet认为这是一个不好的例子,并建议使用AppendLine和AppendFormat的组合。
我意识到我从来没有真正确定自己对使用这些方法的“首选”方法。我想我可能会开始使用以下内容,但有兴趣了解其他人使用的“最佳实践”:
sbuilder.AppendFormat("{0} line", "First").AppendLine();
sbuilder.AppendFormat("{0} line", "Second").AppendLine();

// as opposed to:

sbuilder.AppendLine( String.Format( "{0} line", "First"));
sbuilder.AppendLine( String.Format( "{0} line", "Second"));

也许你的代码示例可以同时说明这两种情况? :) - annakata
7个回答

65
我认为使用AppendFormatAppendLine的方法不仅更易读,而且比调用AppendLine(string.Format(...))方法更高效。

后者会创建一个全新的字符串,然后将其整体附加到现有的构建器中。虽然我不会说“为什么还要使用StringBuilder?”,但它似乎与StringBuilder的精神有点违背。


没问题,我完全可以接受这个任务(顺便说一下,感谢你首先让我接受这个任务)。 - Neil Barnwell
1
没问题 - 如果我的语气在原始评论中显得粗鲁,我很抱歉。多任务会让我有时变得这样 :( - Jon Skeet

14

只需创建一个扩展方法。

public static StringBuilder AppendLine(this StringBuilder builder, string format, params object[] args)
{
    builder.AppendFormat(format, args).AppendLine();
    return builder;
}

我喜欢这种方法的原因:

  • 避免使用AppendLine(string.Format(...))时产生的开销,如上所述。
  • 防止我忘记在结尾添加.AppendLine()部分(这种情况相当普遍)。
  • 更易读(但这更多是个人观点)。

如果你不喜欢它被称为“AppendLine”,你可以将其更改为“AppendFormattedLine”或其他你想要的名称。不过,我喜欢所有对“AppendLine”的调用都与其他调用对齐:

var builder = new StringBuilder();

builder
    .AppendLine("This is a test.")
    .AppendLine("This is a {0}.", "test");

每当您使用 StringBuilder 的 AppendFormat 方法的一个重载时,请添加其中之一。


11

String.format方法在内部创建了一个StringBuilder对象。

sbuilder.AppendLine( String.Format( "{0} line", "First"));

会创建一个额外的StringBuilder实例,包含其所有开销。


mscorlib、Commonlauageruntimelibary、System.String.Format的反射器

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}

2
如果性能很重要,尽可能避免使用AppendFormat()。相反,应该使用多个Append()或者AppendLine()调用。这样会使你的代码变得更大且难以阅读,但是它更快,因为不需要进行字符串解析。字符串解析比你想象中的要慢。我通常使用:
sbuilder.AppendFormat("{0} line", "First");
sbuilder.AppendLine();
sbuilder.AppendFormat("{0} line", "Second");
sbuilder.AppendLine();

除非性能至关重要,否则我会使用以下方法:
sbuilder.Append("First");
sbuilder.AppendLine(" line");
sbuilder.Append("Second");
sbuilder.AppendLine(" line");

(当然,如果“First”和“Second”不是字符串字面量,这将更有意义)

我所进行的基准测试表明,使用单独的Append()调用而不是带有4个参数的单个AppendFormat()调用可以提高5倍的性能。 - Chris

0

AppendFormat()比AppendLine(String.Format())更易读


0

我更喜欢这个结构:

sbuilder.AppendFormat("{0} line\n", "First");

虽然可以说将换行符分开处理也有一定的道理。


我倾向于使用\r\n,但我更喜欢Environment.NewLine,尽管它使用起来很麻烦。因此提出这个问题。 - Neil Barnwell

0

仅仅使用这个是不是太糟糕了

sbuilder.AppendFormat("{0} line\n", first);

我的意思是,我知道它不是跨平台的或者其他什么,但在十分之九的情况下,它能够完成工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接