kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

.NETのStringBuilder vs String.Concatについて(少し修正)

(コメントをいただいたので、4と10を変更しました)
Performance Tips: System.Text.StringBuilder and String.Concat - Feng Yuan (袁峰) - Site Home - MSDN Blogs
文字連結にSystem.Text.StringBuilderを無条件に使うものじゃないよという話です。簡単に翻訳してみます。突っ込みとかあればよろしく。怒られたら消します(^^;。

  1. String.Concat(str1, str2)は二つの文字列連結で最高の性能だよ!StringBuilderなんか使っちゃだめだよ。
  2. String.Concat(str1, str2, str3) と String.Concat(str1, str2, str3, str4)は3つか4つの文字列連結では大体大丈夫。この場合もStringBuilder使っちゃだめだよ。
  3. 四つ以上の複雑な文字列連結でもstring.concat使ってね。片方が空の文字列でもString.Concatは無駄な文字列生成しないからいいよ。
  4. stringの配列を連結する場合、String.Joinが完ぺきだよ。String.Join(String, String[], int, int)を使えば配列の一部の要素を連結することもできるしね。
  5. String.Concatで連結する場合、boxingが起きないようにしてね。たとえば、path + '\\' + filenameだとcharだからboxingが発生するよ。path + "\\" + filenameみたいにstringだけにしてね。
  6. StringBuilder.Append(expr1 + expr2 + expr3)なんか書いちゃだめだよ。Append(expr1).Append(expr2).Append(expr3)みたいに書いてね。
  7. StringBuilder.ToStringは常に新しいstringを別に作っちゃうよ。String.Concat()なら連結対象の文字列が空文字であった場合、新しいstring作らないからいいよ。
  8. StringBuilderは新しく領域作っちゃうから、二重に取られちゃうんで、out of memory出すことがあるよ。大体25%位の領域が無駄になるよ。
  9. String.Formatは内部でStringBuilder.AppendFormatを使っているから、"{0}.{1}"みたいな単純な書式編集なら普通に文字列連結したほうが性能いいよ。でもローカライズで国ごとの書式編集する場合は別だよ。
  10. StringBuilderを頻繁に使う必要がある場合、StringBuilderのインスタンスをその都度作るのではなく、生成済みのインスタンスを使いまわすようにしてね。ただ、その場合スレッド間でStringBuilderのインスタンスを共有しないようにしてね。.NET 4.5でも同じことをやっているよ。

(8/15追記)
コメントをいただいた@yfakariyaさん、@c_nyanさんありがとうございます。string.format便利なんでつい簡単な連結でも使うことがありますね。ただこれもどんな場合でもダメとかじゃなくて、プログラム中に高頻度で使用するとか、サービスのように常駐しているものでもない限り、神経質なまでに気にする必要はないかなぁと思います。
ありがちなところとしてはログのための書式制御ですかね。比較的高頻度で呼び出され、なおかつ書式制御したい場所なので、注意したいところです。