TextBox.Text += "string"; 与 TextBox.AppendText("string"); 的区别

9

这两种方法有什么不同?

它们中有一种更有效吗?

我在想,也许AppendText()使用了类似于StringBuilder的方法,即它使用自己的缓存而不是每次创建和追加一个新字符串,这是真的吗?

谢谢。


1
在反射器中查看它,AppendText 仅通过计算结束位置然后通过 .SelectedText 添加来追加。 - Alex K.
文档:http://msdn.microsoft.com/library/system.windows.forms.textboxbase.appendtext(v=vs.110).aspx - Felipe Oriani
3个回答

18

根据 MSDN 文档的 “Remarks” 部分中明确提到的内容,AppendText 方法使用户能够在不使用文本连接的情况下向文本控件的内容追加文本,这可以在需要许多连接时获得更好的性能。

你的问题是:

这两种方法有什么区别?

我们都知道如何使用 TextBox.Text += something; 即创建并每次追加一个新字符串,但我无法找到任何代码片段来了解 AppendText 的工作原理,即它是否内部使用 StringBuilder 或其他内容。

哪种方法更有效?

我认为上面的问题的答案将取决于具体情况,(基于测试案例观察)

如果Multiline属性设置为false,则连接 (+=)效果更好,但另一方面Multiline属性设置为true,则AppendText的性能要好得多。

编辑 根据来自 Rawling 的评论,我在自定义的 Win-form 解决方案中,使用一个简单的 textbox,使用简单的 for-loop 将一个简单的字符串 hello 追加了10000次。

    private void btnAppendText_Click(object sender, EventArgs e)
    {
        txtText.Text = string.Empty;
        DateTime startTime = DateTime.Now;
        for (int i = 0; i < 10000; i++)
        {
            txtText.AppendText(s);
        }
        DateTime endTime = DateTime.Now;
        txtTime.Text = (endTime.Ticks - startTime.Ticks).ToString();
    }

    private void btnConcante_Click(object sender, EventArgs e)
    {
        txtText.Text = string.Empty;
        DateTime startTime = DateTime.Now;
        for (int i = 0; i < 5000; i++)
        {
            txtText.Text += s;
        }
        DateTime endTime = DateTime.Now;
        txtTime.Text = (endTime.Ticks - startTime.Ticks).ToString();
    }

输出非常令人惊讶,
测试1:多行属性为true 我不得不将迭代次数减半,即5000次文本连接,因为它太耗时间了。

btnAppendText_ClicktxtTime 上的输出是 37222129,10000次迭代需要近3-4秒钟
btnConcante_ClicktxtTime 上的输出是 14449906487,仅进行5000次迭代就需要超过25分钟。

从上面的结果可以清楚地看出,当 Multilinetrue 时,AppendTextConcatenation 更快更有效。

测试2:多行属性为false

btnConcante_ClicktxtTime 上的输出是 39862280,10000次迭代需要近3-4秒钟
btnAppendText_ClicktxtTime 上的输出是 1043279672,10000次迭代需要近2-3分钟

从上面的结果可以清楚地看出,当 Multilinefalse 时,ConcatenationAppendText 更快更有效。









































1
MSDN文档实际上是垃圾。AppendText并不比连接更有效率。我进行了性能测试,.Text +=.AppendText 快几个数量级。 - Rawling
@dbw - 不是这样的 - 我们有反射器 :) 微软代码并没有受到保护,可以被故意查看。 - Ondrej Svejdar
1
@Rawling .Text += 并不更快,请看我的编辑答案。 - Deepak Bhatia
1
@Rawling,你的电脑或测试用例上还有其他问题吗?我正在使用.NET Framework 4客户端框架的Windows应用程序,你能提供一些关于你的测试用例的详细信息吗? - Deepak Bhatia
2
@dbw 我尽可能地复制了您的测试(切换到.NET 4客户端配置文件,使用类变量而不是字符串文字,添加5个字符而不是一个,循环10k而不是1k次),我的+=循环仍然在3秒内完成,而我的AppendText运行大约2分钟。我猜MSDN文档并不是完全垃圾 - 它正确地说它可以产生更好的性能,因为您已经见证了它!- 但我很想知道为什么我们看到如此相反的结果。与所有性能问题一样,这取决于OP对其真实世界使用情况进行分析! - Rawling
显示剩余3条评论

0

AppendText与StringBuilder无关。实际上,Text方法似乎更简单(可能更高效)。参考这两种方法的源代码:

public void AppendText(string text)
{
    if (text.Length > 0)
    {
        int start;
        int length;
        this.GetSelectionStartAndLength(out start, out length);
        try
        {
            int endPosition = this.GetEndPosition();
            this.SelectInternal(endPosition, endPosition, endPosition);
            this.SelectedText = text;
        }
        finally
        {
            if (base.Width == 0 || base.Height == 0)
            {
                this.Select(start, length);
            }
        }
    }
}


public override string Text {
  get {
    return base.Text;
  }
  set {
    if (value != base.Text) {
      base.Text = value;
      if (base.IsHandleCreated) {
        base.SendMessage(185, 0, 0);
      }
    }
  }
}

我可能错了,但它似乎甚至无法正确地保留选择 :-/ 例如,我已经放置了一个 KeyDown 处理程序,当你按下 Control 键时调用 AppendText,但它仍然会清除你所做的任何选择。 - Rawling
@Rawling - 谢谢更新,实际上我是从源代码(头编译器)中猜测它的作用,而不是真正尝试看它在现实生活中如何运作 :) 我已经相应地编辑了我的答案。 - Ondrej Svejdar

0
作为对dbw的补充(以及万一有人能找到我犯错的地方),这是我的性能测试:
private void Form1_Click(object sender, EventArgs e)
{
    Stopwatch sw = new Stopwatch();

    sw.Reset();
    textBox1.Text = "";
    sw.Start();
    for (int i = 0; i < 10000; i++)
    {
        textBox1.Text += s;
    }
    sw.Stop();
    var e1 = sw.Elapsed;

    sw.Reset();
    textBox1.Text = "";
    sw.Start();
    for (int i = 0; i < 10000; i++)
    {
        textBox1.AppendText(s);
    }
    sw.Stop();
    var e2 = sw.Elapsed;
}

我看到e1大约需要3秒钟,而e2则需要大约2分钟。


我在第一个案例中将循环减少到 1000,因为它需要更多时间。在调试时,输出结果为 TotalSeconds = 16.334709399999998,而使用 AppendText 进行 10000 次迭代后,TotalSeconds = 3.7410611 - Deepak Bhatia
请将属性“Multiline”设置为“true”,尝试运行相同的代码。 - Deepak Bhatia
1
@dbw 不错。我的Multiline结果是相反的!微软在某个地方记录这些信息是很好的... - Rawling
Multiline 为 false 时,我得到了相反的结果。 - Deepak Bhatia

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