C# StringBuilderの使い方完全ガイド|stringとの違い・Append・高速化のコツを初心者向けに解説
はじめに
C#で文字列を組み立てるとき、最初は次のように+演算子や+=を使うことが多いでしょう。
C#string message = "Hello";
message += " ";
message += "World";
少量の文字列であれば、この書き方でも問題ありません。しかし、ループの中で何百回、何千回も文字列を追加する場合は、stringの連結よりもStringBuilderを使ったほうが効率的になることがあります。
C# StringBuilderは、文字列を何度も追加・挿入・置換・削除する場面で役立つクラスです。stringが変更できない文字列であるのに対し、StringBuilderは中身を変更しながら文字列を組み立てられるため、大量の文字列処理で無駄なオブジェクト生成を抑えやすくなります。Microsoft Learnでも、Stringオブジェクトは不変であり、繰り返し変更する場合はSystem.Text.StringBuilderを使うことでパフォーマンス向上につながる場合があると説明されています。Microsoft Learn+1
この記事では、C#のStringBuilderについて、初心者向けに基本構文、AppendやAppendLineの使い方、stringとの違い、高速化のコツ、注意点までわかりやすく解説します。
1. C#のStringBuilderとは?文字列を効率よく扱うための基本
1-1. StringBuilderの役割とできること
StringBuilderは、文字列を効率よく組み立てるためのクラスです。正式にはSystem.Text.StringBuilderクラスで、変更可能な文字の並びを表します。Microsoft LearnのAPIリファレンスでも、StringBuilderは「変更可能な文字の文字列」を表すクラスとして説明されています。Microsoft Learn+1
StringBuilderを使うと、主に次のような操作ができます。
文字列を末尾に追加する
改行付きで文字列を追加する
指定位置に文字列を挿入する
一部の文字列を置換する
指定範囲の文字列を削除する
内容を空にする
最終的に
string型へ変換する
たとえば、以下のように文字列を順番に追加できます。
C#using System.Text;
StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
string result = sb.ToString();
Console.WriteLine(result);
実行結果は次のとおりです。
C#Hello World
StringBuilderは、最終的に完成した文字列をToString()で取り出して使うのが基本です。
1-2. stringとの違いを初心者向けに解説
stringとStringBuilderの大きな違いは、「中身を変更できるかどうか」です。
stringは不変、つまり一度作成した文字列の中身を変更できません。たとえば次のコードでは、textに文字列を追加しているように見えます。
C#string text = "A";
text += "B";
text += "C";
しかし実際には、既存の"A"という文字列そのものが変更されているわけではありません。"AB"、"ABC"という新しい文字列が作られ、変数textが新しい文字列を参照するようになります。stringは不変であり、System.Stringの操作では新しい文字列オブジェクトが作成されることがあるため、繰り返し変更する処理ではオーバーヘッドが大きくなる場合があります。Microsoft Learn+1
一方、StringBuilderは中身を変更しながら文字列を組み立てられます。
C#StringBuilder sb = new StringBuilder();
sb.Append("A");
sb.Append("B");
sb.Append("C");
Console.WriteLine(sb.ToString());
このように、何度も文字列を追加する処理では、StringBuilderのほうが向いているケースがあります。
1-3. StringBuilderが必要になる代表的な場面
StringBuilderが役立つ代表的な場面は、文字列を何度も変更する処理です。
たとえば、次のようなケースではStringBuilderが候補になります。
ループ内で文字列を大量に連結する
複数行のテキストを組み立てる
CSV文字列を作成する
HTMLやSQLの一部を動的に組み立てる
ログメッセージを条件付きで作成する
大量データを1つの文字列にまとめる
特に、ループ内で+=を使って文字列を追加し続けるコードは、StringBuilderへの置き換えを検討する価値があります。
C#StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 1000; i++)
{
sb.Append(i);
sb.Append(",");
}
string result = sb.ToString();
このように、追加回数が多い処理ではStringBuilderのメリットが出やすくなります。
1-4. StringBuilderを使わなくてもよいケース
一方で、すべての文字列連結にStringBuilderを使う必要はありません。
たとえば、次のような少量の文字列連結では、+演算子や文字列補間のほうが読みやすいです。
C#string name = "田中";
int age = 25;
string message = name + "さんは" + age + "歳です。";
または、文字列補間を使うとさらにわかりやすくなります。
C#string message = $"{name}さんは{age}歳です。";
1回だけの連結、短いメッセージ作成、可読性を優先したい場面では、無理にStringBuilderを使わなくてもかまいません。Microsoft Learnでも、C#で複数の文字列を連結する方法として、+演算子、文字列補間、String.Format、String.Concat、String.Join、StringBuilder.Appendなど複数の選択肢が紹介されています。Microsoft Learn
2. C#でStringBuilderを使う準備と基本構文
2-1. StringBuilderを使うための名前空間
C#でStringBuilderを使うには、通常はファイルの先頭に次の名前空間を追加します。
C#using System.Text;
StringBuilderはSystem.Text名前空間に含まれています。using System.Text;を書いておくと、コード内でStringBuilderと短く書けます。Microsoft Learn+1
C#using System;
using System.Text;
class Program
{
static void Main()
{
StringBuilder sb = new StringBuilder();
sb.Append("C#");
sb.Append(" StringBuilder");
Console.WriteLine(sb.ToString());
}
}
もしusing System.Text;を書かない場合は、次のように完全修飾名で書くこともできます。
C#System.Text.StringBuilder sb = new System.Text.StringBuilder();
ただし、通常はusing System.Text;を使うほうが読みやすいです。
2-2. StringBuilderのインスタンスを作成する方法
StringBuilderを使うには、まずインスタンスを作成します。
C#StringBuilder sb = new StringBuilder();
その後、Appendなどのメソッドを使って文字列を追加していきます。
C#StringBuilder sb = new StringBuilder();
sb.Append("こんにちは");
sb.Append("、");
sb.Append("C#");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#こんにちは、C#
StringBuilderは、作成してから必要な文字列を追加し、最後にToString()でstringに変換する流れが基本です。
2-3. 初期文字列を指定して作成する方法
最初から文字列を入れた状態でStringBuilderを作成することもできます。
C#StringBuilder sb = new StringBuilder("最初の文字列");
sb.Append("を追加しました。");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#最初の文字列を追加しました。
既存の文字列に対して、さらに内容を追加・編集していきたい場合に便利です。
C#string baseText = "商品一覧:";
StringBuilder sb = new StringBuilder(baseText);
sb.AppendLine();
sb.AppendLine("・りんご");
sb.AppendLine("・みかん");
Console.WriteLine(sb.ToString());
2-4. Capacityを指定して作成する方法
StringBuilderにはCapacityという考え方があります。Capacityは、内部的に確保されている文字数の容量を表すプロパティです。あらかじめ完成後の文字列サイズがある程度予想できる場合は、初期容量を指定すると、内部バッファーの拡張回数を減らせる可能性があります。StringBuilderにはCapacityプロパティや、容量を指定するコンストラクターが用意されています。Microsoft Learn+1
C#StringBuilder sb = new StringBuilder(1000);
このコードでは、初期容量として1000文字分を指定しています。
たとえば、1000件のデータを連結することがわかっている場合は、次のように初期容量を指定できます。
C#StringBuilder sb = new StringBuilder(5000);
for (int i = 1; i <= 1000; i++)
{
sb.Append("Item");
sb.Append(i);
sb.Append(",");
}
string result = sb.ToString();
ただし、初期容量は必ず指定しなければならないものではありません。まずは通常のnew StringBuilder()で書き、必要に応じて最適化するのが現実的です。
3. StringBuilderの基本的な使い方
3-1. Appendで文字列を追加する
Appendは、StringBuilderの末尾に文字列や値を追加するメソッドです。StringBuilderで最もよく使う基本メソッドといえます。
C#StringBuilder sb = new StringBuilder();
sb.Append("C#");
sb.Append(" ");
sb.Append("StringBuilder");
sb.Append("の使い方");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#C# StringBuilderの使い方
Appendには文字列だけでなく、数値や真偽値なども渡せます。
C#StringBuilder sb = new StringBuilder();
int count = 10;
double price = 120.5;
bool isActive = true;
sb.Append("件数:");
sb.Append(count);
sb.Append(", 価格:");
sb.Append(price);
sb.Append(", 有効:");
sb.Append(isActive);
Console.WriteLine(sb.ToString());
Appendは戻り値として同じStringBuilderインスタンスを返すため、次のようにメソッドチェーンで書くこともできます。
C#StringBuilder sb = new StringBuilder();
sb.Append("A")
.Append("B")
.Append("C");
Console.WriteLine(sb.ToString());
ただし、長くなりすぎると読みにくくなるため、適度に改行するとよいでしょう。
3-2. AppendLineで改行付きの文字列を追加する
AppendLineは、文字列を追加したあとに改行も追加するメソッドです。複数行のテキストを作るときに便利です。APIリファレンスでも、AppendLineは指定した文字列と既定の行終端記号を現在のStringBuilderの末尾へ追加するメソッドとして説明されています。Microsoft Learn
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("1行目");
sb.AppendLine("2行目");
sb.AppendLine("3行目");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#1行目
2行目
3行目
AppendLine()のように引数なしで呼び出すと、空行を追加できます。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("タイトル");
sb.AppendLine();
sb.AppendLine("本文です。");
Console.WriteLine(sb.ToString());
複数行のメッセージ、ログ、メール本文、設定ファイルのような文字列を作るときに使いやすいメソッドです。
3-3. Insertで指定位置に文字列を挿入する
Insertは、指定した位置に文字列や値を挿入するメソッドです。
C#StringBuilder sb = new StringBuilder("C# Builder");
sb.Insert(3, "String");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#C# StringBuilder
Insert(3, "String")は、インデックス3の位置に"String"を挿入しています。
文字列の先頭に追加したい場合は、位置に0を指定します。
C#StringBuilder sb = new StringBuilder("World");
sb.Insert(0, "Hello ");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#Hello World
ただし、頻繁に先頭や途中へ挿入する処理が多い場合は、コードの見通しが悪くなることがあります。必要な順番でAppendできないかも検討しましょう。
3-4. Replaceで文字列を置換する
Replaceは、StringBuilder内の指定した文字列を別の文字列に置換するメソッドです。
C#StringBuilder sb = new StringBuilder("Hello C#");
sb.Replace("Hello", "こんにちは");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#こんにちは C#
テンプレート文字列の一部をあとから置き換えるような使い方もできます。
C#StringBuilder sb = new StringBuilder();
sb.Append("{{name}}さん、ようこそ。");
sb.Replace("{{name}}", "佐藤");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#佐藤さん、ようこそ。
ただし、単純なテンプレート置換であれば文字列補間のほうが読みやすいこともあります。
C#string name = "佐藤";
string message = $"{name}さん、ようこそ。";
Replaceは、すでに組み立てた文字列全体に対して一括置換したいときに便利です。
3-5. Removeで指定範囲の文字列を削除する
Removeは、指定した位置から指定した文字数分を削除するメソッドです。
C#StringBuilder sb = new StringBuilder("Hello C# World");
sb.Remove(5, 3);
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#Hello World
この例では、インデックス5から3文字分、つまり" C#"を削除しています。
CSVの末尾に余分なカンマが付いた場合、それを削除するような用途にも使えます。
C#StringBuilder sb = new StringBuilder();
sb.Append("りんご,");
sb.Append("みかん,");
sb.Append("バナナ,");
if (sb.Length > 0)
{
sb.Remove(sb.Length - 1, 1);
}
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#りんご,みかん,バナナ
ただし、CSVを作るだけなら、後述するstring.Joinのほうが簡潔に書ける場合もあります。
3-6. Clearで内容を空にする
Clearは、StringBuilderの内容を空にするメソッドです。
C#StringBuilder sb = new StringBuilder();
sb.Append("最初の内容");
Console.WriteLine(sb.ToString());
sb.Clear();
sb.Append("新しい内容");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#最初の内容
新しい内容
同じStringBuilderインスタンスを再利用したい場合に便利です。
C#StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 3; i++)
{
sb.Clear();
sb.Append("処理番号:");
sb.Append(i);
Console.WriteLine(sb.ToString());
}
Clearを使うと、毎回new StringBuilder()で作り直す必要がない場面もあります。ただし、無理に再利用してコードがわかりにくくなるなら、新しく作ったほうがよい場合もあります。
3-7. ToStringでstring型に変換する
StringBuilderで組み立てた内容を通常のstringとして使うには、ToString()を呼び出します。
C#StringBuilder sb = new StringBuilder();
sb.Append("C#");
sb.Append(" StringBuilder");
string result = sb.ToString();
Console.WriteLine(result);
StringBuilderそのものはstringではありません。そのため、string型の引数を受け取るメソッドに渡す場合や、完成した文字列として保存したい場合はToString()が必要です。Microsoft LearnのToStringメソッドの説明でも、StringBuilderオブジェクトをStringオブジェクトに変換するにはToStringを呼び出す必要があると説明されています。Microsoft Learn
C#void ShowMessage(string message)
{
Console.WriteLine(message);
}
StringBuilder sb = new StringBuilder();
sb.Append("メッセージです。");
ShowMessage(sb.ToString());
4. string連結とStringBuilderの違いを比較
4-1. stringはなぜ大量連結に弱いのか
stringは不変なので、文字列を変更しているように見える処理でも、実際には新しい文字列が作られる場合があります。たとえば、次のようなコードです。
C#string text = "";
for (int i = 0; i < 10000; i++)
{
text += i.ToString();
}
このコードでは、ループのたびにtextへ新しい文字列を追加しています。少ない回数なら問題になりにくいですが、回数が多くなると、新しい文字列オブジェクトの作成やコピーの負担が増える可能性があります。Microsoft Learnでも、Stringは不変であり、繰り返し変更する必要がある場合は新しいStringオブジェクト作成のオーバーヘッドが高くなる可能性があると説明されています。Microsoft Learn+1
4-2. StringBuilderが高速化につながる仕組み
StringBuilderは、内部に変更可能な文字列バッファーを持ち、そこへ文字を追加していきます。毎回新しいstringを作り直すのではなく、同じStringBuilderの内容を変更しながら組み立てるため、繰り返し連結する処理で効率がよくなる場合があります。StringBuilderは変更可能な文字シーケンスを表す文字列のようなオブジェクトとして説明されています。Microsoft Learn+1
C#StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append(i);
}
string result = sb.ToString();
このように、ループで文字列を増やしていく処理では、StringBuilderがよく使われます。
4-3. +演算子・string.Concat・string.Joinとの違い
C#で文字列を連結する方法は、StringBuilderだけではありません。
代表的な方法には次のようなものがあります。
C#string a = "Hello";
string b = "World";
string result1 = a + " " + b;
string result2 = string.Concat(a, " ", b);
string result3 = string.Join(" ", a, b);
それぞれの特徴は次のとおりです。
+演算子は、短い文字列を直感的に連結できます。
C#string message = "こんにちは、" + name + "さん";
文字列補間は、変数を含む文字列を読みやすく書けます。
C#string message = $"こんにちは、{name}さん";
string.Concatは、複数の文字列を連結するメソッドです。
C#string message = string.Concat("A", "B", "C");
string.Joinは、区切り文字を入れながら連結する場合に便利です。
C#string csv = string.Join(",", names);
StringBuilderは、何度も追加・編集しながら文字列を組み立てる場合に向いています。
C#StringBuilder sb = new StringBuilder();
foreach (string name in names)
{
sb.AppendLine(name);
}
string result = sb.ToString();
C#では、文字列連結の方法として+、+=、文字列補間、String.Format、String.Concat、String.Join、StringBuilder.Appendなどが利用できます。Microsoft Learn
4-4. どの方法を使うべきか判断する基準
文字列連結の方法は、処理内容によって使い分けるのが大切です。
少量の文字列を1回だけ連結するなら、+演算子や文字列補間が読みやすいです。
C#string message = $"{userName}さん、こんにちは";
配列やリストを区切り文字付きで連結するなら、string.Joinが便利です。
C#List<string> items = new List<string> { "A", "B", "C" };
string result = string.Join(",", items);
ループ内で何度も文字列を追加するなら、StringBuilderを検討します。
C#StringBuilder sb = new StringBuilder();
foreach (string item in items)
{
sb.AppendLine(item);
}
string result = sb.ToString();
目安としては、次のように考えるとわかりやすいです。
| 場面 | おすすめ |
|---|---|
| 文字列が少ない | +、文字列補間 |
| 変数を埋め込みたい | 文字列補間 |
| 配列やリストを区切り文字でつなぐ | string.Join |
| 大量に追加する | StringBuilder |
| 途中で挿入・置換・削除する | StringBuilder |
4-5. ループ処理での文字列連結比較
ループ内で文字列を連結する例を比較してみましょう。
まずはstringの+=を使う例です。
C#string result = "";
for (int i = 1; i <= 5; i++)
{
result += i + ",";
}
Console.WriteLine(result);
次にStringBuilderを使う例です。
C#StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++)
{
sb.Append(i);
sb.Append(",");
}
string result = sb.ToString();
Console.WriteLine(result);
少ない回数なら、どちらでも体感差はほとんどありません。しかし、連結回数が多い場合は、StringBuilderのほうが適していることがあります。
ただし、実際の速度差は、文字列の長さ、ループ回数、.NETのバージョン、実行環境によって変わります。最終的には、必要に応じてベンチマークを取り、計測して判断することが重要です。
5. StringBuilderを使った実践コード例
5-1. 複数行の文字列を作成する例
StringBuilderは、複数行の文字列を作るときに便利です。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("お知らせ");
sb.AppendLine("---------------");
sb.AppendLine("本日の営業時間は10:00〜18:00です。");
sb.AppendLine("ご来店をお待ちしております。");
string message = sb.ToString();
Console.WriteLine(message);
実行結果は次のようになります。
C#お知らせ
---------------
本日の営業時間は10:00〜18:00です。
ご来店をお待ちしております。
AppendLineを使うことで、\nや\r\nを自分で何度も書かなくて済みます。
5-2. CSV形式の文字列を作成する例
CSV形式の文字列を作る場合にもStringBuilderを使えます。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("Id,Name,Price");
sb.AppendLine("1,りんご,120");
sb.AppendLine("2,みかん,100");
sb.AppendLine("3,バナナ,150");
string csv = sb.ToString();
Console.WriteLine(csv);
実行結果は次のとおりです。
C#Id,Name,Price
1,りんご,120
2,みかん,100
3,バナナ,150
リストからCSVを作る場合は、次のようにも書けます。
C#List<string[]> rows = new List<string[]>
{
new[] { "1", "りんご", "120" },
new[] { "2", "みかん", "100" },
new[] { "3", "バナナ", "150" }
};
StringBuilder sb = new StringBuilder();
sb.AppendLine("Id,Name,Price");
foreach (string[] row in rows)
{
sb.AppendLine(string.Join(",", row));
}
string csv = sb.ToString();
Console.WriteLine(csv);
単純な区切り文字連結にはstring.Joinを使い、全体の複数行組み立てにはStringBuilderを使うと、読みやすくなります。
5-3. HTML文字列を組み立てる例
HTML文字列をコードで組み立てる場合にもStringBuilderは使えます。
C#List<string> fruits = new List<string>
{
"りんご",
"みかん",
"バナナ"
};
StringBuilder sb = new StringBuilder();
sb.AppendLine("<ul>");
foreach (string fruit in fruits)
{
sb.Append(" <li>");
sb.Append(fruit);
sb.AppendLine("</li>");
}
sb.AppendLine("</ul>");
string html = sb.ToString();
Console.WriteLine(html);
実行結果は次のようになります。
HTML<ul>
<li>りんご</li>
<li>みかん</li>
<li>バナナ</li>
</ul>
ただし、WebアプリケーションでHTMLを生成する場合は、XSS対策のためにHTMLエスケープが必要です。ユーザー入力をそのままHTMLへ埋め込むのは避けましょう。ASP.NETなどのフレームワークでは、ビューやテンプレートエンジンの仕組みを使うほうが安全で保守しやすいケースが多いです。
5-4. ログメッセージを組み立てる例
条件に応じてログメッセージを作る場合にもStringBuilderを使えます。
C#string userName = "tanaka";
bool isSuccess = false;
string errorMessage = "パスワードが正しくありません。";
StringBuilder sb = new StringBuilder();
sb.AppendLine("ログイン処理");
sb.Append("ユーザー名: ");
sb.AppendLine(userName);
sb.Append("結果: ");
sb.AppendLine(isSuccess ? "成功" : "失敗");
if (!isSuccess)
{
sb.Append("エラー: ");
sb.AppendLine(errorMessage);
}
string log = sb.ToString();
Console.WriteLine(log);
実行結果は次のようになります。
C#ログイン処理
ユーザー名: tanaka
結果: 失敗
エラー: パスワードが正しくありません。
複数の条件によって追加する内容が変わる場合、StringBuilderを使うと1つずつメッセージを積み上げられます。
5-5. 条件分岐を使って文字列を追加する例
StringBuilderは、条件によって文章を変える処理にも向いています。
C#string name = "佐藤";
int point = 1200;
bool isPremium = true;
StringBuilder sb = new StringBuilder();
sb.Append(name);
sb.Append("さん、こんにちは。");
if (isPremium)
{
sb.AppendLine();
sb.Append("プレミアム会員特典が利用できます。");
}
if (point > 1000)
{
sb.AppendLine();
sb.Append("ポイントが1000を超えています。クーポンと交換できます。");
}
string message = sb.ToString();
Console.WriteLine(message);
実行結果は次のとおりです。
C#佐藤さん、こんにちは。
プレミアム会員特典が利用できます。
ポイントが1000を超えています。クーポンと交換できます。
条件が多い文章を+演算子だけで組み立てると読みにくくなりがちです。AppendやAppendLineを使うことで、処理の流れに沿って文章を追加できます。
6. StringBuilderで高速化するためのコツ
6-1. 初期Capacityを適切に指定する
完成する文字列の長さがある程度わかっている場合は、StringBuilderの初期Capacityを指定するとよい場合があります。
C#StringBuilder sb = new StringBuilder(10000);
Capacityを指定しておくと、内部バッファーの拡張回数を減らせる可能性があります。特に、大量データを扱う処理では効果が出ることがあります。
C#int count = 10000;
StringBuilder sb = new StringBuilder(count * 10);
for (int i = 0; i < count; i++)
{
sb.Append("Item");
sb.Append(i);
sb.AppendLine();
}
ただし、必要以上に大きな容量を指定するとメモリを余分に使うことになります。正確な値にこだわりすぎず、おおよその目安で指定するのが現実的です。
6-2. 不要なToString呼び出しを避ける
StringBuilderを使っている途中で何度もToString()を呼び出すと、そのたびにstringが作られます。
C#StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append(i);
string temp = sb.ToString();
Console.WriteLine(temp);
}
このようなコードでは、StringBuilderを使っていても不要な文字列生成が増えてしまいます。
完成した文字列が必要なタイミングでだけToString()を呼び出しましょう。
C#StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append(i);
}
string result = sb.ToString();
Console.WriteLine(result);
StringBuilderをstringとして扱うにはToString()が必要ですが、呼び出し回数は最小限にするのが基本です。
6-3. ループ内での使い方に注意する
StringBuilderはループ内の文字列連結に向いていますが、使い方を間違えると効果が薄くなります。
よくない例は、ループの中で毎回StringBuilderを作り直すことです。
C#string result = "";
for (int i = 0; i < 1000; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append(result);
sb.Append(i);
result = sb.ToString();
}
これではStringBuilderのメリットを活かしにくくなります。
基本的には、ループの外でStringBuilderを作成し、ループ内ではAppendします。
C#StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append(i);
}
string result = sb.ToString();
この形が、StringBuilderを使った文字列組み立ての基本です。
6-4. AppendFormatより文字列補間が適するケース
StringBuilderにはAppendFormatというメソッドがあります。これは、書式指定を使って文字列を追加するメソッドです。AppendFormatは.NETの複合書式指定を使って値をテキスト表現に変換し、現在のStringBuilderへ追加するメソッドです。Microsoft Learn
C#StringBuilder sb = new StringBuilder();
string name = "田中";
int age = 30;
sb.AppendFormat("{0}さんは{1}歳です。", name, age);
Console.WriteLine(sb.ToString());
一方、最近のC#では文字列補間のほうが読みやすい場面が多いです。
C#StringBuilder sb = new StringBuilder();
string name = "田中";
int age = 30;
sb.Append($"{name}さんは{age}歳です。");
Console.WriteLine(sb.ToString());
単純な値の埋め込みであれば、文字列補間のほうが直感的です。複雑な書式指定や既存コードとの整合性が必要な場合はAppendFormat、読みやすさを優先する場合は文字列補間、と使い分けるとよいでしょう。
6-5. 再利用するときはClearを使う
同じStringBuilderを何度も使う場合は、Clear()で中身を空にできます。
C#StringBuilder sb = new StringBuilder();
foreach (string name in new[] { "佐藤", "鈴木", "田中" })
{
sb.Clear();
sb.Append("こんにちは、");
sb.Append(name);
sb.Append("さん");
Console.WriteLine(sb.ToString());
}
Clear()を使うと、同じインスタンスを再利用できます。
ただし、再利用にこだわりすぎる必要はありません。小さな処理では、毎回new StringBuilder()しても問題にならないことが多いです。再利用することでコードが複雑になるなら、読みやすさを優先しましょう。
6-6. パフォーマンス改善が必要か計測して判断する
StringBuilderは便利ですが、使えば必ず速くなるわけではありません。
たとえば、次のような短い文字列であれば、文字列補間のほうが読みやすく、十分に高速です。
C#string message = $"{name}さん、注文番号は{orderId}です。";
パフォーマンス改善を目的にStringBuilderを使うなら、実際に処理時間やメモリ使用量を計測することが大切です。
C#var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// 計測したい処理
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++)
{
sb.Append(i);
}
string result = sb.ToString();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms");
「なんとなく速そうだから使う」のではなく、「大量の連結がある」「実際に遅い」「計測して改善が確認できる」といった場面で使うのが理想です。
7. StringBuilderの注意点とよくある失敗
7-1. 少量の文字列連結では効果が小さい
StringBuilderは大量の文字列連結に向いていますが、少量の文字列では効果が小さいことがあります。
次のようなコードでは、文字列補間で十分です。
C#string message = $"{lastName} {firstName}さん、こんにちは。";
これを無理にStringBuilderで書くと、かえって冗長になります。
C#StringBuilder sb = new StringBuilder();
sb.Append(lastName);
sb.Append(" ");
sb.Append(firstName);
sb.Append("さん、こんにちは。");
string message = sb.ToString();
この程度であれば、文字列補間のほうが読みやすいです。StringBuilderは、文字列の追加回数が多い場合や、処理の途中で挿入・置換・削除が必要な場合に使うとよいでしょう。
7-2. スレッドセーフではない点に注意する
StringBuilderは、通常の使い方ではスレッドセーフではありません。つまり、複数のスレッドから同じStringBuilderインスタンスを同時に変更すると、意図しない結果になる可能性があります。
たとえば、複数スレッドで共有するフィールドとしてStringBuilderを持ち、同時にAppendするような設計は注意が必要です。
C#class LogBuffer
{
private StringBuilder _builder = new StringBuilder();
public void Add(string message)
{
_builder.AppendLine(message);
}
}
このようなクラスを複数スレッドから同時に使う場合は、ロックなどの同期処理を検討する必要があります。
C#class LogBuffer
{
private readonly object _lock = new object();
private readonly StringBuilder _builder = new StringBuilder();
public void Add(string message)
{
lock (_lock)
{
_builder.AppendLine(message);
}
}
}
ただし、基本的にはStringBuilderをメソッド内のローカル変数として使えば、スレッドの問題は起きにくくなります。
7-3. ToStringしないとstringとして扱えない
StringBuilderで作った内容は、そのままstringとして扱えるわけではありません。
C#StringBuilder sb = new StringBuilder();
sb.Append("Hello");
// string message = sb; // エラー
string型の変数へ代入するには、ToString()が必要です。
C#string message = sb.ToString();
メソッドの引数がstring型の場合も同じです。
C#void Send(string message)
{
Console.WriteLine(message);
}
StringBuilder sb = new StringBuilder();
sb.Append("送信メッセージ");
Send(sb.ToString());
初心者のうちは、最後にToString()することを忘れがちなので注意しましょう。
7-4. 可読性が下がる書き方を避ける
StringBuilderは便利ですが、何でもAppendで書けばよいわけではありません。
次のようなコードは、内容がわかりにくくなりがちです。
C#sb.Append("名前:");
sb.Append(name);
sb.Append(",");
sb.Append("年齢:");
sb.Append(age);
sb.Append(",");
sb.Append("住所:");
sb.Append(address);
短いメッセージなら、文字列補間のほうが読みやすい場合があります。
C#string message = $"名前:{name},年齢:{age},住所:{address}";
一方、複数行や条件分岐がある場合はStringBuilderが読みやすくなります。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine($"名前: {name}");
sb.AppendLine($"年齢: {age}");
if (!string.IsNullOrEmpty(address))
{
sb.AppendLine($"住所: {address}");
}
可読性を保つには、StringBuilderを使う理由があるかを意識することが大切です。
7-5. 過剰な最適化をしない
StringBuilderはパフォーマンス改善に役立つことがありますが、過剰に使うとコードが複雑になります。
たとえば、次のような単純な文字列作成では、StringBuilderは不要です。
C#string title = "C# StringBuilderの使い方";
また、短い文章を1回作るだけなら、次のように文字列補間で十分です。
C#string message = $"{userName}さん、ログインしました。";
パフォーマンスは重要ですが、最初から細かく最適化しすぎると、保守しにくいコードになります。まずは読みやすいコードを書き、問題が出たら計測し、必要な箇所にStringBuilderを使うのがおすすめです。
8. StringBuilderの主要メソッド一覧
8-1. Append系メソッドの一覧
StringBuilderでよく使うAppend系メソッドは次のとおりです。
| メソッド | 役割 |
|---|---|
Append | 末尾に文字列や値を追加する |
AppendLine | 末尾に文字列と改行を追加する |
AppendFormat | 書式指定を使って文字列を追加する |
AppendJoin | 区切り文字を使って複数の値を追加する |
基本はAppendとAppendLineを覚えておけば十分です。
C#StringBuilder sb = new StringBuilder();
sb.Append("名前: ");
sb.AppendLine("田中");
sb.Append("年齢: ");
sb.AppendLine("30");
Console.WriteLine(sb.ToString());
AppendFormatは書式指定が必要なときに使えます。
C#StringBuilder sb = new StringBuilder();
sb.AppendFormat("価格は{0:N0}円です。", 12000);
Console.WriteLine(sb.ToString());
8-2. 編集系メソッドの一覧
StringBuilderは、追加だけでなく編集もできます。
| メソッド | 役割 |
|---|---|
Insert | 指定位置に文字列や値を挿入する |
Replace | 指定した文字列を置換する |
Remove | 指定範囲の文字列を削除する |
Clear | 内容を空にする |
例は次のとおりです。
C#StringBuilder sb = new StringBuilder("Hello World");
sb.Insert(6, "C# ");
sb.Replace("World", "StringBuilder");
sb.Remove(0, 6);
Console.WriteLine(sb.ToString());
InsertやReplaceは便利ですが、多用しすぎると処理が追いにくくなることがあります。できるだけ自然な順番でAppendできるように設計すると、読みやすいコードになります。
8-3. プロパティ一覧
StringBuilderでよく使うプロパティには、LengthとCapacityがあります。
| プロパティ | 役割 |
|---|---|
Length | 現在の文字数を取得または設定する |
Capacity | 現在確保されている容量を取得または設定する |
MaxCapacity | 最大容量を取得する |
Lengthは、文字列が空かどうかを確認したり、末尾の文字を削除したりするときによく使います。
C#StringBuilder sb = new StringBuilder();
sb.Append("A,B,C,");
if (sb.Length > 0)
{
sb.Remove(sb.Length - 1, 1);
}
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#A,B,C
Capacityは、パフォーマンスを意識するときに使うことがあります。
C#StringBuilder sb = new StringBuilder(1000);
Console.WriteLine(sb.Capacity);
8-4. よく使うメソッドの使い分け早見表
StringBuilderのメソッドを使い分けるときは、次の表を参考にしてください。
| やりたいこと | 使うメソッド |
|---|---|
| 末尾に文字列を追加したい | Append |
| 改行付きで追加したい | AppendLine |
| 指定位置に入れたい | Insert |
| 文字列を置き換えたい | Replace |
| 一部を削除したい | Remove |
| 中身を空にしたい | Clear |
| 完成した文字列を取り出したい | ToString |
| 現在の文字数を知りたい | Length |
| 初期容量を調整したい | Capacity |
初心者がまず覚えるべきなのは、Append、AppendLine、ToStringの3つです。
C#StringBuilder sb = new StringBuilder();
sb.Append("C#");
sb.AppendLine(" StringBuilder");
sb.AppendLine("基本はAppendとAppendLineです。");
string result = sb.ToString();
Console.WriteLine(result);
その後、必要に応じてInsert、Replace、Remove、Clearを覚えるとよいでしょう。
9. StringBuilderに関するよくある質問
9-1. StringBuilderはいつ使うべき?
StringBuilderは、文字列を何度も追加・変更する場面で使うのがおすすめです。
特に、次のようなケースではStringBuilderが向いています。
ループ内で大量に文字列を連結する
複数行のテキストを作る
条件によって追加する文字列が変わる
途中で挿入、置換、削除を行う
最終的に1つの大きな文字列を作る
一方、短い文字列を1回だけ作るなら、+演算子や文字列補間で十分です。
C#string message = $"{name}さん、こんにちは。";
StringBuilderは「大量に組み立てる」「何度も変更する」ときに使う、と覚えるとわかりやすいです。
9-2. stringとの速度差はどれくらい?
stringとStringBuilderの速度差は、処理内容によって変わります。
少量の文字列連結では、差がほとんど出ないこともあります。むしろ、StringBuilderを使うことでコードが長くなり、可読性が下がる場合もあります。
一方、何千回、何万回とループで文字列を追加する場合は、StringBuilderのほうが有利になることがあります。Microsoft Learnでも、ループ内で多数の文字列を連結するような場面では、StringBuilderによってパフォーマンスを向上できる場合があると説明されています。Microsoft Learn+1
ただし、実際の差は環境によって変わるため、重要な処理では計測して判断しましょう。
9-3. AppendとAppendLineの違いは?
Appendは、文字列をそのまま末尾に追加します。
C#StringBuilder sb = new StringBuilder();
sb.Append("A");
sb.Append("B");
sb.Append("C");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#ABC
AppendLineは、文字列を追加したあとに改行も追加します。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("A");
sb.AppendLine("B");
sb.AppendLine("C");
Console.WriteLine(sb.ToString());
実行結果は次のようになります。
C#A
B
C
1行の中で続けて追加したい場合はAppend、行ごとに追加したい場合はAppendLineを使います。
9-4. StringBuilderは初期化後に中身を変更できる?
はい、変更できます。StringBuilderは、作成後にAppend、Insert、Replace、Remove、Clearなどで中身を変更できます。StringBuilderは変更可能な文字シーケンスを表すクラスです。Microsoft Learn+1
C#StringBuilder sb = new StringBuilder("Hello");
sb.Append(" World");
sb.Replace("World", "C#");
sb.Insert(0, "Message: ");
Console.WriteLine(sb.ToString());
実行結果は次のとおりです。
C#Message: Hello C#
このように、StringBuilderは後から内容を編集できる点がstringとの大きな違いです。
9-5. .NETのバージョンで使い方は変わる?
基本的な使い方は大きく変わりません。StringBuilderは長く使われている基本的なクラスで、Append、AppendLine、Insert、Replace、Remove、Clear、ToStringといった主要な使い方は、現在の.NETでも一般的に利用できます。Microsoft LearnのStringBuilder APIリファレンスでも、これらのメソッドやプロパティが確認できます。Microsoft Learn+1
ただし、C#や.NETのバージョンによって、文字列補間やパフォーマンス最適化の仕組みが改善されることがあります。たとえば、C#の文字列補間は継続的に機能追加や改善が行われています。Microsoft Learn+1
初心者のうちは、まず次の基本形を覚えれば十分です。
C#using System.Text;
StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.AppendLine(" World");
string result = sb.ToString();
.NETの細かなバージョン差よりも、「stringは不変」「StringBuilderは変更可能」「大量連結ではStringBuilderを検討する」という基本を理解することが大切です。
まとめ
C#のStringBuilderは、文字列を効率よく組み立てるための便利なクラスです。
stringは不変であり、繰り返し変更する処理では新しい文字列オブジェクトが作成されることがあります。一方、StringBuilderは変更可能な文字列のようなオブジェクトとして動作し、AppendやAppendLineを使って内容を追加しながら最終的な文字列を作れます。Microsoft Learn+1
基本的な流れは次のとおりです。
C#using System.Text;
StringBuilder sb = new StringBuilder();
sb.Append("C#");
sb.Append(" StringBuilder");
sb.AppendLine("の使い方");
string result = sb.ToString();
StringBuilderで特に重要なメソッドは、末尾に追加するAppend、改行付きで追加するAppendLine、完成した文字列を取り出すToStringです。さらに、必要に応じてInsert、Replace、Remove、Clearを使うと、文字列の挿入・置換・削除・再利用もできます。
ただし、少量の文字列連結ではStringBuilderを使う必要はありません。短い文字列なら、+演算子や文字列補間のほうが読みやすいことが多いです。StringBuilderは、ループ内で大量に文字列を追加する場合、複数行のテキストを作る場合、条件に応じて文字列を組み立てる場合などに使うと効果的です。
C#で文字列処理を書くときは、「読みやすさ」と「処理効率」のバランスが重要です。まずはシンプルに書き、文字列連結が多くなってきたらStringBuilderを検討しましょう。

