Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
StringBuilder在C#中的性能?_C# - Fatal编程技术网

StringBuilder在C#中的性能?

StringBuilder在C#中的性能?,c#,C#,我有一个StringBuilder对象,我在其中添加了一些字符串,如下所示: 我想知道哪种方法更好,首先是: StringBuilder sb = new StringBuilder(); sb.Append("Hello" + "How" + "are" + "you"); 第二个是: StringBuilder sb = new StringBuilder(); sb.Append("Hello").Append("How").Append("are").Append("you"); 第

我有一个
StringBuilder
对象,我在其中添加了一些字符串,如下所示:

我想知道哪种方法更好,首先是:

StringBuilder sb = new StringBuilder();
sb.Append("Hello" + "How" + "are" + "you");
第二个是:

StringBuilder sb = new StringBuilder();
sb.Append("Hello").Append("How").Append("are").Append("you");

第一种方法效率更高。编译器将其转换为以下单个调用:

StringBuilder sb = new StringBuilder();
sb.Append("HelloHowareyou");
衡量绩效

知道哪个更快的最好方法是测量它。我要直截了当地说:以下是结果(时间越短意味着速度越快):

给定的数字是在紧循环中执行1亿次操作的秒数

结论

  • 最快的是使用字符串文字和
    +
  • 但是如果您有变量,那么使用
    追加
    +
    更快。由于额外调用了
    String.Concat
    ,第一个版本的速度较慢

如果您想自己测试,下面是我用来获取上述计时的程序:

using System;
using System.Text;

public class Program
{
    public static void Main()
    {
        DateTime start, end;
        int numberOfIterations = 100000000;
        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello" + "How" + "are" + "you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\" + \"How\" + \"are\" + \"you\")", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello").Append("How").Append("are").Append("you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\").Append(\"How\").Append(\"are\").Append(\"you\")", start, end);

        string a = "Hello";
        string b = "How";
        string c = "are";
        string d = "you";

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a + b + c + d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a + b + c + d)", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a).Append(b).Append(c).Append(d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a).Append(b).Append(c).Append(d)", start, end);

        Console.ReadLine();
    }

    private static void DisplayResult(string name, DateTime start, DateTime end)
    {
        Console.WriteLine("{0,-60}: {1,6:0.000}s", name, (end - start).TotalSeconds);
    }
}
使用系统;
使用系统文本;
公共课程
{
公共静态void Main()
{
日期时间开始,结束;
int numberOfIterations=100000000;
开始=DateTime.UtcNow;
对于(int i=0;i
在当前示例中,字符串文字:

"Hello" + "How" + "are" + "you"
将由编译器编译为一个常量字符串文字,因此在技术上比:

sb.Append("Hello").Append("How").Append("are").Append("you");
但是,如果要使用字符串变量:

sb.Append(s1 + s2 + s3 + s4);
然后,后者会更快,因为前者可能会在将最终字符串传递到
Append
方法之前创建一系列字符串(由于串联),而后者则会避免额外的字符串创建(但会权衡额外的方法调用和内部缓冲区大小调整)


更新:为了进一步说明,在只有4个项目被连接的情况下,编译器将发出对
String.Concat(String,String,String,String)
的调用,知道字符串的长度和数量将比
StringBuilder

更有效。在第一种情况下,编译器将构造单个字符串,因此只需调用Append一次。然而,我怀疑这会有很大的不同。你的测量结果显示了什么?

第二种方法更好。字符串是不可变的,这意味着当您使用sb.Append(“Hello”+“How”+“are”+“you”)时,您正在创建字符串的多个副本

e、 g

然后

然后

等等

第二段代码的性能要好得多

编辑:当然这没有考虑到编译器的优化,但最好按预期使用该类

正如人们所指出的,由于这些是文本,编译器会对这些操作进行优化——但我的观点是,字符串连接是StringBuilder试图避免的事情

例如,循环多次:

var someString = "";

foreach (var s in someListOfStrings) 
{
    someString += s;
}
不如做:

var sb = new StringBuilder();

foreach(var s in someListOfStrings)
{
    sb.Append(s);
}

sb.ToString();
因为这可能会更快,因为正如我前面所说的,字符串是不可变的

我认为OP是在谈论使用连接,因为

sb.Append("Hello" + "How");
似乎完全没有意义的时候

sb.Append("HelloHow");
会更符合逻辑吗


在我看来,在OPs的思想中,占位符文本最终将成为一堆变量…

编译器将在编译时连接字符串常量。如果连接的字符串表达式不超过四个,编译器将发出对
string.Concat

s + t + u + v ==> String.Concat(s, t, u, v)
这比
StringBuilder
执行得更快,因为
StringBuilder
可能需要调整其内部缓冲区的大小,而
Concat
可以提前计算总的结果长度。但是,如果预先知道结果字符串的最大长度,则可以通过指定初始工作缓冲区大小来初始化
StringBuilder

var sb = new StringBuilder(initialBufferSize);

StringBuilder
通常用于循环和其他动态场景中,在这种情况下执行速度比
s+=t
快。

请参阅。这已经涵盖到了死亡:-)你会发现有趣的我的问题是-为什么你会想做“你好”+“如何”等,当“你好”会很好?这个问题的真正意义是什么?因为我的答案因为技术原因而遭到抨击,我认为这不是问题的关键……你是
sb.Append("Hello" + "How");
sb.Append("HelloHow");
s + t + u + v ==> String.Concat(s, t, u, v)
var sb = new StringBuilder(initialBufferSize);