C#で文字列を結合するには、「+」演算子を使う方法と、StringBuilderクラスのAppendメソッドを使う方法があります。
本記事では、両者の違いと使い分けについて紹介します。
サンプルコード
using System;
using System.Text;
class StringConcatSample
{
static void Main(string[] args)
{
//「+」演算子での結合
string plusResult = "文字列";
plusResult += "結合";
//StringBuilderクラスのAppendメソッドでの結合
var sbResult = new StringBuilder("文字列");
sbResult.Append("結合");
Console.WriteLine("「+」演算子:{0}, StringBuilder:{1}",plusResult,sbResult.ToString());
//「+」演算子:文字列結合, StringBuilder:文字列結合
}
}
「+」演算子の結合でも、StringBuilderのAppendメソッドを使用しても、得られる結果は同じとなります。
「+」演算子による結合
C#のStringオブジェクトは、内部的には固定の文字列として扱われるため、変更ができません。
そのため、「+」演算子による結合では、下記3種類のString オブジェクトを生成することで、文字列結合を実現しています。
- 結合前の文字列
- 結合する文字列
- 結合後の文字列
したがって、文字列の追加・変更が多くなるほどオーバーヘッドが増加し、ガベージコレクションへの影響が大きくなります。
StringBuilderクラスのAppendメソッドによる結合
対してStringBuilderクラスは、一定のサイズの可変長の文字列として扱われます。
そのため、StringBuilderクラスを使用して文字列を追加・変更しても、Stringオブジェクトのようにオブジェクト生成と破棄が頻繁に行われることはありません。
つまり、文字列の追加・変更時のオーバーヘッドは「+」演算子を使用した方法よりも圧倒的に少なくなります。
但し、最初に確保したサイズ以上の文字列結合となった場合は、オーバーヘッドが大きくなる可能性があります。
※元サイズから確保領域を2倍に拡張(メモリ領域の再割り当て)するため。
この問題に対し、「独習C#」の書籍には以下のような対策が紹介されています。
あらかじめ文字数が想定できているならば、インスタンス化の際にサイズを明示しておくことをお勧めします。これによって、StringBuilderによる連結処理をより効率化できます。
var builder = new StringBuilder(1000);
山田 祥寛. 独習C# 新版 . 株式会社 翔泳社.
両者の使い分け
文字列の追加・変更が多い場合やループ内ではStringBuilder.Appendを、数回の場合は「+」演算子での結合を使用すればよいかと思います。
※文字列の追加・変更が数回(「独習C#」の検証では5、6回程度)である場合は、「+」演算子による処理の方がパフォーマンスが高くなります。
書籍やマイクロソフト公式には以下のように記載されています。
ループ内での文字列連結はStringBuilderを、単発的な文字列連結には「 +」演算子を、という使い分けをお勧めします。
山田 祥寛. 独習C# 新版 . 株式会社 翔泳社.
次の条件下では、StringBuilderクラスの使用を検討してください。
・アプリケーションで、デザイン時に文字列に対して不明な数の変更を加えることが予想される場合 (たとえば、ユーザー入力を含む文字列の数を連結するためにループを使用する場合など)。
・アプリが文字列に大幅な変更を加えることが予想される場合。
マイクロソフト公式 StringBuilderクラス
また、StringBuilderクラスには、文字列検索のメソッドがありません。
文字列検索を行いたい場合は、一度Stringオブジェクトに変換する等の処理が必要となります。
詳細は公式の「 StringBuilder オブジェクト内のテキストの検索」をご参照ください。