C#
 Computer >> コンピューター >  >> プログラミング >> C#

C#のStringBuilderクラスとは?目的と使い方を徹底解説

C#における文字列の不変性(イミュータブル)

C#では、文字列(string型)は不変(イミュータブル)です。つまり、一度作成した文字列は後から変更することができません。文字列に対して何らかの変更操作を行うと、元の文字列はそのまま残り、変更内容を含んだ新しい文字列が返されます。

string word = "aaabbbccc";
string newWord = word.Replace('b', 'd');
Console.WriteLine(word);     // aaabbbccc と出力される
Console.WriteLine(newWord);  // aaadddccc と出力される

この例のように、Replaceメソッドを実行しても元のwordは変化せず、新しい文字列newWordが生成されていることがわかります。

StringBuilderクラスの役割

StringBuilderクラスは、内容を変更できる「可変(ミュータブル)な文字列」を表すクラスです。不変の文字列を表すstring型とは内部実装が異なり、効率的に文字列を編集できるよう設計されています。

stringオブジェクトを変更するたびに新しいコピーが作成されるため、同じ文字列を繰り返し変更するとパフォーマンスが低下します。少数回の処理であれば影響はほぼありませんが、大量のループ処理では顕著な問題になります。StringBuilderを使えば、文字の追加・削除・置換・挿入を効率的に行うことができます。

StringBuilderの内部動作

StringBuilderは内部的にバッファを保持しており、そこに文字を格納します。バッファに空きがある場合はそのままデータを追加し、空きがない場合は新しいバッファを作成して旧データをコピーした上で、新たなデータを追加します。

var sb = new StringBuilder();
for (int i = 0; i < 10; i++)
{
    sb.Append("a");
}
Console.WriteLine(sb.ToString()); // aaaaaaaaaa と出力される

StringBuilderのコンストラクタ

StringBuilderオブジェクトは、さまざまな方法で初期化できます。

// 空のインスタンスを初期化
var sb1 = new StringBuilder();

// 指定した容量で初期化
var sb2 = new StringBuilder(capacity: 10);

// 指定した文字列で初期化
var sb3 = new StringBuilder(value: "Hello World");

// 容量と最大容量を指定して初期化
var sb4 = new StringBuilder(capacity: 20, maxCapacity: 50);

// 文字列と容量を指定して初期化
var sb5 = new StringBuilder(value: "Hello", capacity: 20);

// 部分文字列と容量を指定して初期化
var sb6 = new StringBuilder(value: "Hello World", startIndex: 0, length: 5, capacity: 20);

Length・Capacity・MaxCapacityの関係

StringBuilderには、現在保持している文字数を示すLengthプロパティがあります。文字を追加するとLengthは増加していき、現在確保されている最大文字数であるCapacity(容量)に達するまで続きます。

追加した文字数によってLengthがCapacityを超えると、新しいメモリが割り当てられ、容量が拡張されます。その後、新しい文字が追加され、Lengthプロパティも更新されます。

このメモリの動的な拡張は、MaxCapacityプロパティの値に達するまで続きます。それ以降はこれ以上メモリを割り当てることができず、さらにデータを追加しようとするとArgumentOutOfRangeExceptionまたはOutOfMemoryExceptionがスローされます。

主なメソッド一覧

StringBuilderには、文字列の編集を簡単に行うための便利なメソッドが多数用意されています。

  • Append ― 指定したオブジェクトの文字列表現を現在のインスタンスの末尾に追加します。
  • AppendFormat ― 複合書式指定文字列を処理した結果の文字列を末尾に追加します。各書式項目は対応する引数の文字列表現に置き換えられます。
  • AppendJoin ― 指定した区切り文字でオブジェクト配列の要素を連結し、その結果を現在のインスタンスに追加します。
  • AppendLine ― 既定の改行文字を現在のStringBuilderオブジェクトの末尾に追加します。
  • Clear ― 現在のStringBuilderインスタンスからすべての文字を削除します。
  • CopyTo ― 文字をコピー先のcharスパンまたはchar配列にコピーします。
  • EnsureCapacity ― このインスタンスの容量が少なくとも指定した値になるように保証します。
  • Equals ― このインスタンスと指定されたインスタンスの文字列・Capacity・MaxCapacityが等しい場合にtrueを返します。
  • GetChunks ― 文字のチャンクを反復処理できるオブジェクトを返します。
  • Insert ― 指定した文字位置に、指定したオブジェクトの文字列表現を挿入します。
  • Remove ― 指定した範囲の文字をこのインスタンスから削除します。
  • Replace ― 指定した文字または文字列の出現箇所をすべて、別の文字または文字列に置き換えます。
  • ToString ― 現在のインスタンスをstring型に変換します。

サンプルコード

using System;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        string word = "aaabbbccc";
        string newWord = word.Replace('b', 'd');
        Console.WriteLine(word);     // aaabbbccc
        Console.WriteLine(newWord);  // aaadddccc

        var sb = new StringBuilder();
        for (int i = 0; i < 10; i++)
        {
            sb.Append("a");
        }
        Console.WriteLine(sb.ToString()); // aaaaaaaaaa

        // 各種コンストラクタによる初期化
        var sb1 = new StringBuilder();
        var sb2 = new StringBuilder(capacity: 10);
        var sb3 = new StringBuilder(value: "Hello World");
        var sb4 = new StringBuilder(capacity: 20, maxCapacity: 50);
        var sb5 = new StringBuilder(value: "Hello", capacity: 20);
        var sb6 = new StringBuilder(value: "Hello World", startIndex: 0, length: 5, capacity: 20);
    }
}

実行結果

aaabbbccc
aaadddccc
aaaaaaaaaa

まとめ

C#のstring型は不変であるため、頻繁に文字列を編集する場面ではStringBuilderの利用が推奨されます。特にループ内での連結処理など、大量の文字列操作を行う場合には、パフォーマンス面で大きな差が生じます。用途に応じて両者を使い分けることで、より効率的なコードを書くことができます。

  1. C#のHashtableクラスにおけるIsReadOnlyプロパティとは?使い方を解説

    C#のHashtableクラスには、コレクションの状態を確認するための便利なプロパティが多数用意されています。そのひとつがIsReadOnlyプロパティです。このプロパティは、対象のHashtableが読み取り専用(Read-Only)かどうかを示すbool値を取得します。読み取り専用の場合はtrue、要素の追加や変更が可能な場合はfalseを返します。IsReadOnlyプロパティの使用例以下のコードでは、3つの要素を持つHashtableを作成し、IsReadOnlyプロパティの値をコンソールに出力しています。using System; using System.Collections;

  2. JavaのProcessクラスとは?目的と主なメソッドを実例付きで解説

    概要java.lang.Processクラスは、Objectクラスのサブクラスであり、Runtimeクラスのexec()メソッドによって起動された外部プロセスを表現するためのクラスです。Processオブジェクトを通じて、起動したプロセスの制御や情報の取得を行うことができます。なお、Processクラスは抽象クラスとして定義されているため、直接インスタンス化することはできません。インスタンスは、Runtime.exec()などのメソッドの戻り値として取得します。主なメソッドdestroy(): プロセスを強制終了させるexitValue(): プロセスの終了コードを返すgetErrorStre