文字列の連結

現在開発しているアプリケーションでは、頻繁に大量の文字列連結をしなければならない処理があります。

私は、よくコレクションなどに文字列を格納しておいて、string.Join でまとめて連結する方法を使用しています。
最近は、この方法ばかり使っているため、StringBuilder を使う機会がほとんどありません。

しかし、現在開発しているアプリケーションでは、文字列を連結する速度が非常に大切です。
そこで、文字列の連結の処理速度について、試してみることにしました。

static void Main(string[] args)
{
  var range = Enumerable.Range(0, 100000);
  Execute(“+”, () => {
    var s = string.Empty;
    foreach(var x in range) s += “A”;
  });

  Execute(“StringBuilder”, () => {
    var s = new StringBuilder();
    foreach(var x in range) s.Append(“A”);
    var result = s.ToString();
  });

  Execute(“StringJoin”, () => {
    var s = new List<string>();
    foreach(var x in range) s.Add(“A”);
    var result = string.Join(string.Empty, s.ToArray());
  });

  Console.ReadLine();
}

static void Execute(string name, Action action) {
  var stopWotch = new Stopwatch();
  stopWotch.Reset();
  stopWotch.Start();
  action();
  stopWotch.Stop();
  Console.WriteLine(name + “:” + stopWotch.ElapsedMilliseconds);
}

上記は、”A” を 100000 回連結する処理を、次の 3 つの方法で実行した速度を表示するというものです。

+演算子を使用した場合
StringBuilder を使用した場合
一旦コレクションに格納して string.Join で連結した場合

実行結果は、以下のようになりました。

 +:15668
StringBuilder:4
StringJoin:15

この結果は、予想通りです。
次に、文字列配列に格納されている文字列を連結した場合を試してみます。

var range = Enumerable.Range(0, 10000000).Select(x => x + “”).ToArray();
Execute(“StringBuilder”, () => {
  var s = new StringBuilder();
 foreach(var x in range) s.Append(string.Empty + x);
 var result = s.ToString();
});

Execute(“StringJoin”, () => {
   var result = string.Join(string.Empty, range);
});

上記は、文字列配列の要素を連結した比較です。
結果は、次のようになりました。

StringBuilder:1410
StringJoin:652

この結果も、予想通りです。
最後に、List<string>に格納されている文字列を連結した場合を試してみます。

var range = Enumerable.Range(0, 10000000).Select(x => x + “”).ToList();

直前のコードと比較して上記の部分のみを変更して実行してみました。

StringBuilder:1559
StringJoin:1839

この理由ですが、ToList コレクションオブジェクト型を string.Join メソッドの引数として指定すると、オーバーロードされた IEnumerable<T> 型で受け取ることになるためです。
そして、IEnumerable<T> から配列に変換する処理コスト分だけ遅くなってしまうということでしょう。

以上から、次の結論が得られます。

string.Join が高速なのは、文字列配列を連結するときのみ、それ以外は、StringBuilder を使用した方が高速。

当たり前のような結果ですが、このことが明確にわかったので、今後はうまく使い分けることができそうです。