[C#] StringBuilder と 単純な文字列連結 の比較


htmlで, 色々値を入れたtableを書くことになったとき, 次のようなコードを書きました.

string getHtmlCode(IQueryable<Post> values)
{
  string body = "<table>";
  int counter = 1;
  foreach (var _value in values)
  { 
    body += String.Format(
      "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td></tr>"
      , counter++ 
      , _value.something1
      , _value.something2
      , _value.something3
    );
  }
  body += "</table>";
  return body;
}

そしたら, この場合, 単純な文字列連結ではなく, StringBuilder を使うといい, と, 教えてもらいました!

ということで StringBuilder を使って書き直しました!

string getHtmlCode(IQueryable<Post> values)
{
  var tableBody = new System.Text.StringBuilder();
  tableBody.Append("<table>");
  int counter = 1;
  foreach (var _value in values)
  { 
    tableBody.AppendFormat(
      "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td></tr>"
      , counter++ 
      , _value.something1
      , _value.something2
      , _value.something3
    );
  }
  tableBody.Append("</table>");
  return tableBody.ToString();
}

なぜ?

どうして, この場合(ガンガンループ回す中では)単純な文字連結よりもStringBuilder使ったほうがいいのかも聞きました.

string型は,

連続したメモリ領域を食います.
それで, 文字長がどんどん長くなっていったら,
今までいた場所の(連続した場所)残りが足りなくなったら, いったんそこを開放して, 別のもっと余裕のあるところにメモリを取ります.
それでもまた足りなくなったらまた開放して, 別の広いところにメモリを取って自身を書き込みます.

そうやって開放と取るのを繰り返すのは, とても重いことらしいです.

たぶん, 新婚さんが2人暮らしのマンションに住んでて,
ひとり子供が生まれたので3人暮らしの広さのマンションに引っ越して, (引越代とか色々コストがかかる)
さらにもうひとり二人目の子供が生まれたので4人暮らしのマンションに引っ越して,
みたいのを延々とやることになるからマズイのかなって思いました.
(((o( *゚▽゚* )o)))

いっぽう, StringBuilderのほうは,

あとで足すのをいったん別の場所に(.Append()で)それぞれ置いておいて,
最後に一気に連結します.
だから, メモリ解放と取るのを繰り返すことが無いので, しあわせなようです.

[追記] 私の記憶違いらしく, 違うらしい! コメントで教えていただきました! ありがとうございます!

#あとで読む