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 += opearator または 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 オブジェクトが連結される場合の連結操作に適しています。その場合、個々の連結操作は、コンパイラーによって 1 つの操作に結合されることさえあります。

任意の数の文字列が連結される場合、連結操作には StringBuilder オブジェクトが適しています。たとえば、ループがユーザー入力の乱数の文字列を連結する場合です。

したがって、あなたの場合、文字列の方が優れていると言えます。

編集:

これは終わりのない議論ですが、とにかく、平均していくつの操作があるかを確認し、それぞれのパフォーマンスをテストして結果を比較することをお勧めします.

いくつかのパフォーマンス テスト コードを含む、この問題に関するこの素敵なリンクを確認してください。

于 2012-06-21T07:14:24.870 に答える
1

StringBuilderをお勧めします。変更可能です。それはメモリアロケータにはるかに少ないストレスをかけるはずです:-)

文字列インスタンスは不変です。作成後に変更することはできません。文字列を変更するように見える操作は、代わりに新しいインスタンスを返します。

于 2012-06-21T07:11:22.563 に答える
1

確かにStringBuilder 。文字列は不変であることを覚えておいてください!

編集:3〜4行の場合、Jon Skeetが回答で述べているように、連結が好ましい選択になります

于 2012-06-21T07:09:26.853 に答える
0

stringbuilder はあなたが探しているものです。一般に、何らかのジョブ用の関数がある場合は、ほとんど同じジョブを実行するプロシージャを記述する代わりに、それを利用するようにしてください。

于 2012-06-21T07:14:42.610 に答える