【C#】ループ内での文字列結合は+じゃなくStringBuilderを使っとけ

C#のループ内での文字列結合は+じゃなくStringBuilderを使っとけという話です。

文字列は+するとメモリをアロケーションする

今、メモリ上に文字列「ABCDE」があるとします。

f:id:halya_11:20190523221813p:plain

これに対して「FGHDI」を+演算子でくっつけます。
ソースコード的には以下の通りです。

var text = "ABCDE";

text += "FGHIJ";


しかしこれは内部的にメモリを再割り当てして、結合した文字列をそこに入れるという処理を行っています。

f:id:halya_11:20190523222149p:plain

この処理を頻繁に行うと非効率が生じてしまいます。

ループ内ではStringBuilderを使う

頻繁に文字列の結合を行うようなケースでは、StringBuilderを使うと良いようです。

var builder = new System.Text.StringBuilder("ABCDE");
builder.Append("FGHIJ");

このクラスはメモリをあらかじめある程度確保しておくので結合時にのアロケーションが防げます。
かなり雑な方針を示すならば、ループ内で文字列結合を行う際にはStringBuilderを使った方が良さそうです。
サイズが大きくなりそうならコンストラクタで容量を指定しておくとより良さそうです。

速度を比較する

それでは速度の違いをざっと比較してみます。
まずstringによる文字列結合です。


var sw = System.Diagnostics.Stopwatch.StartNew();

var text = "";

for (int i = 0; i < 100000; i++)
{

    text += "A"; 
}

System.Console.WriteLine(sw.Elapsed);

結果は00:00:13.6183865となりました。遅い。
次にStringBuilderによる結合を試してみます。

var sw = System.Diagnostics.Stopwatch.StartNew();

var text = new System.Text.StringBuilder();

for (int i = 0; i < 100000; i++)
{

    text.Append("A"); 

}

System.Console.WriteLine(sw.Elapsed);

結果は00:00:00.0032037となりました。
こんなに変わるんですね・・

詳しくはこちら

このあたりのより正確な情報は下記のページにまとめられています。
詳細を知りたい方はこちらをご参照ください。

dobon.net