14

在我的项目中,我正在遍历数据视图结果。

 string html =string.empty;
 DataView dV = data.DefaultView;
 for(int i=0;i< dV.Count;i++)
 {
     DataRowView rv = dV[i];
     html += rv.Row["X"].Tostring();
 }

dV 中的行数始终为 3 或 4。

在这种情况下使用字符串 concat += 运算符或 StringBuilder 更好吗?为什么?

4

6 回答 6

39

我会StringBuilder在这里使用,只是因为它描述了你在做什么。

对于 3 或 4 个字符串的简单连接,它可能不会产生任何显着差异,字符串连接甚至可能会稍微快一些 - 但如果你错了并且有很多行,StringBuilder将开始变得更有效率,并且它总是更能描述你在做什么。

或者,使用类似的东西:

string html = string.Join("", dv.Cast<DataRowView>()
                                .Select(rv => rv.Row["X"]));

请注意,您目前在字符串之间没有任何分隔符。你确定那是你想要的吗?(另请注意,您的代码目前没有多大意义 - 您没有i在循环中使用。为什么?)

我有一篇关于字符串连接的文章,其中更详细地说明了为什么值得使用StringBuilder以及何时使用。

编辑:对于那些怀疑字符串连接可以更快的人,这里有一个测试 - 故意“讨厌”数据,但只是为了证明它是可能的:

using System;
using System.Diagnostics;
using System.Text;

class Test
{
    static readonly string[] Bits = { 
        "small string",
        "string which is a bit longer",
        "stirng which is longer again to force yet another copy with any luck"
    };

    static readonly int ExpectedLength = string.Join("", Bits).Length;

    static void Main()        
    {
        Time(StringBuilderTest);
        Time(ConcatenateTest);
    }

    static void Time(Action action)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        // Make sure it's JITted
        action();
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 10000000; i++)
        {
            action();
        }
        sw.Stop();
        Console.WriteLine("{0}: {1} millis", action.Method.Name,
                          (long) sw.Elapsed.TotalMilliseconds);
    }

    static void ConcatenateTest()
    {
        string x = "";
        foreach (string bit in Bits)
        {
            x += bit;
        }
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }

    static void StringBuilderTest()
    {
        StringBuilder builder = new StringBuilder();
        foreach (string bit in Bits)
        {
            builder.Append(bit);
        }
        string x = builder.ToString();
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }
}

我的机器上的结果(用 编译/o+ /debug-):

StringBuilderTest: 2245 millis
ConcatenateTest: 989 millis

我已经运行了几次,包括颠倒测试的顺序,结果是一致的。

于 2012-06-21T07:11:49.007 回答
5

建议使用 StringBuilder .. 你为什么不自己做一个分析,然后决定什么是最适合你的..

var stopWatch=new StopWatch();
stopWatch.Start();
string html =string.empty;
        DataView dV = data.DefaultView;
        for(int i=0;i< dV.Count;i++)
        {
           html += dV.Row["X"].Tostring();
        } 
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());

var stopWatch=new StopWatch();
stopWatch.Start();
string html =new StringBuilder();
        DataView dV = data.DefaultView;
        for(int i=0;i< dV.Count;i++)
        {
           html.Append(dV.Row["X"].ToString());
        } 
var finalHtml=html.ToString();
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());
于 2012-06-21T07:14:31.143 回答
2

从文档:

如果串联固定数量的 String 对象,则 String 类更适合串联操作。在这种情况下,编译器甚至可以将各个连接操作组合成一个操作。

如果串联任意数量的字符串,则 StringBuilder 对象更适合串联操作;例如,如果一个循环连接随机数量的用户输入字符串。

所以在你的情况下,我会说字符串更好。

编辑:

这是一个没有结束的讨论,无论如何我建议你检查你平均有多少操作并测试每个操作的性能以比较结果。

检查这个关于这个问题的不错的链接,包括一些性能测试代码。

于 2012-06-21T07:14:24.870 回答
1

StringBuilder是肯定的。字符串是不可变的记住!

编辑:对于 3-4 行,连接将是首选,正如 Jon Skeet 在他的回答中所说

于 2012-06-21T07:09:26.853 回答
1

推荐使用StringBuilder。它是可变的。它应该对内存分配器施加更少的压力:-)

字符串实例是不可变的。创建后无法更改。任何看似更改字符串的操作都会返回一个新实例。

于 2012-06-21T07:11:22.563 回答
0

stringbuilder 是您正在寻找的。一般来说,如果有某个功能可以用于某项工作,请尝试使用它,而不是编写一些可以完成几乎相同工作的程序。

于 2012-06-21T07:14:42.610 回答