Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.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
C# foreach中的Stringbuilder比for中的要慢,String.Join()在集合中很糟糕?_C#_Arrays_Performance_String - Fatal编程技术网

C# foreach中的Stringbuilder比for中的要慢,String.Join()在集合中很糟糕?

C# foreach中的Stringbuilder比for中的要慢,String.Join()在集合中很糟糕?,c#,arrays,performance,string,C#,Arrays,Performance,String,在这里看到一个关于连接字符串的问题后,我做了一些测试,并了解到在foreach中连接字符串比使用for循环和使用数组中的索引要慢。for循环不应该因为数组上的绑定检查而变慢吗?(对foreach上不存在的字符串[i]进行绑定检查) 另一件我不明白的事情是string.Join()在列表中的慢度 编辑:将错误和更新源更新为最终源(删除最后一个“,”) 以下是测试结果: 以下是资料来源: public static void Main(string[] Args) { List<str

在这里看到一个关于连接字符串的问题后,我做了一些测试,并了解到在foreach中连接字符串比使用for循环和使用数组中的索引要慢。for循环不应该因为数组上的绑定检查而变慢吗?(对foreach上不存在的字符串[i]进行绑定检查)

另一件我不明白的事情是string.Join()在列表中的慢度

编辑:将错误和更新源更新为最终源(删除最后一个“,”)

以下是测试结果:

以下是资料来源:

public static void Main(string[] Args)
{
    List<string> strings = new List<string>() {};
    for (double d = 0; d < 12000; d++) {
        strings.Add(d.ToString());
    }

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Performance(() =>
    {
            StringBuilder sb = new StringBuilder();
            foreach (string s in strings)
            {
                sb.Append(s);
                sb.Append(",");
            }
            sb.Remove(sb.Length - 1, 1);
    }, "StringBuilder foreach");

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Performance(() =>
    {
        StringBuilder sb = new StringBuilder();
        int max = strings.Count-1;
        int i;
        for (i = 0; i < max; i++)
        {
            sb.Append(strings[i]);
            sb.Append(",");
        }
        sb.Append(strings[i]);
    }, "StringBuilder for");

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Performance(() =>
    {
        string s = string.Join(",", strings);
    }, "String.Join");


}
public static void Performance(Action fn, string prefix)
{
    var timer = new Stopwatch();
    timer.Start();

    for (var i = 0; i < 10000; ++i)
    {
        fn();
    }

    timer.Stop();

    Console.WriteLine("{0} {1} Time: {2}ms ({3})", prefix, fn.ToString(), timer.ElapsedMilliseconds, timer.ElapsedTicks);
}
它可能对数组有好处,但对集合字符串有好处。Join非常糟糕,对大字符串更是如此

如果您希望比较以下内容,仅供参考:

Windows 7 64bit
CPU Type    QuadCore AMD Phenom II X4 945
CPU Clock   3000 MHz
L3 Cache    6 MB  (On-Die, ECC, NB-Speed)
North Bridge Clock  2010.8 MHz
Memory 8190 MB
Memory Bus  804.3 MHz DDR3-1600
Motherboard Chipset AMD 790X, AMD K10
Memory Timings  8-9-9-24  (CL-RCD-RP-RAS)
Command Rate (CR)   1T
for循环不应该因为数组上的绑定检查而变慢吗

否,CLR可以将其优化为1检查是否可以验证边界。这使得

 int max = strings.Count - 1;
一个糟糕的优化。在FX 1.1中,它会让您付出代价。(这也不正确)


foreach
需要做更多的工作(通过电子计算器)。请注意,差异很小

查看ILSpy中的IL代码

foreach循环有一个隐式try。。最后,for循环没有

在foreach内部还有对MoveNext的隐式调用。MoveNext有很多开销,包括在最终对列表执行索引操作以获取条目之前进行版本更改检查

理论上,foreach可以更快,但它显然比裸for循环做更多的工作


这是在vs2010下。不确定其他版本如何处理此问题

marjino,字符串不是值类型。或者你可以评论字符串的速度有多慢。Join在列表上-在数组上非常快。foreach涉及为集合创建枚举数实例,而for循环不涉及该实例。边界测试以某种方式涉及这两种操作。另外,
用于(int i=0;i字符串是引用类型。此外,您的
for
循环结束得太早了一步。for循环测试缺少最后一个字符串。Try
int max=Strings.Count;
Hank int max=string.Count;是正确的,-1是一个错误,但int max会进行优化。使用我发布的新代码并尝试。foreach必须创建一个枚举数或者在每个for上,但是for必须对字符串[i]执行数百万次绑定检查除非编译器在那里做了一些魔术…但是你有一点需要编译器优化绑定检查。我尝试将int I;移出操作,它将for的速度降低了5%。因此必须对I变量进行一些优化。好的,我现在认为编译器无法像你所想的那样优化这个循环,因为选择超出了对其进行迭代的方法的范围(因此另一个线程可能会更改它),这就是为什么int max会进行优化(它会跳过每次迭代时读取属性)。@Marino:只需将属性内联留给JIT。这是一个老话题。
Windows 7 64bit
CPU Type    QuadCore AMD Phenom II X4 945
CPU Clock   3000 MHz
L3 Cache    6 MB  (On-Die, ECC, NB-Speed)
North Bridge Clock  2010.8 MHz
Memory 8190 MB
Memory Bus  804.3 MHz DDR3-1600
Motherboard Chipset AMD 790X, AMD K10
Memory Timings  8-9-9-24  (CL-RCD-RP-RAS)
Command Rate (CR)   1T
 int max = strings.Count - 1;