【C#】StringBuilderを使って文字列処理を効率よく行おう!Stringとの使いわけ

プログラミング

こんにちは、村正です!

今回は「StringBuider型を使って文字列処理を効率よく行おう!」というお話です!

文字列と言えばString型というイメージがあると思いますが、文字列を頻繁に処理(結合や削除、変換など)する場合はStringBuilder型を使ったほうが効率が良いです。

というわけで今回はStringBuider型について、string型との違いと使いかたについて紹介していきたいと思います。

それでは本編いってみましょう!

string型 と StringBuiler型 の違い

string型StringBuiler型は「文字列の変更時に新しくオブジェクトを作成する(メモリを確保する)かどうか」という違いがあります。

string型オブジェクトは、格納する文字列を変更するたびに新しくその文字列用のstring型オブジェクトを作成します。新規で作成したstring型オブジェクト(の参照)を格納することで、内容を変更してます。

対してStringBuilder型オブジェクトは、あらかじめ余裕を持ってメモリを確保しておきます。変更後の文字列がそのメモリ範囲内に収まる文字列の場合はオブジェクトを新しく作成することなく、内容を変更できます。

図で表すと以下のようになります。

たとえば以下のように繰り返し文などで頻繁に文字列”あいう”を結合をする場合は、string型を使ってしまうと結合のたびに新しくオブジェクトを作成してしまう(メモリを確保してしまう)ので、StringBuider型を使うべきなのです。

// Stringを使うと微妙
string message_01 = "";
for (int i = 1; i <= 100; i++)
{
    // 末尾に"あ"を追加(この度に新しくオブジェクトを作成する処理が入る)
    message_01 += "あいう";            
}

// StringBuilderを使おう!
StringBuilder message_02 = new StringBuilder();
for (int i = 1; i <= 100; i++)
{
    //末尾に"あ"を追加(メモリ内に収まらない場合のみオブジェクトを作成する処理が入る)
    message_02.Append("あいう");                   
}
string newMessage = message_02.ToString();     //string型に変換

「文字列を頻繁に処理(結合や削除、変換など)する場合はStringBuilder型を使うべき!」だということが分かったところで、StringBuilder型の使い方について見ていきましょう!

StringBuider の使いかた

StringBuider オブジェクトの作成

StringBuiderオブジェクトはnewで作ることができます。

// ①オブジェクトの作成(16文字文のメモリを確保)
StringBuilder sb_01 = new StringBuilder();

// ②オブジェクトの作成(好きな文字数分のメモリを確保)
StringBuilder sb_02 = new StringBuilder(123);

// ③引数を指定することで初期文字列を設定できる
StringBuilder sb_03 = new StringBuilder("初期文字列");

// ④初期文字列と初期メモリ確保量を設定できる
StringBuilder sb_04 = new StringBuilder("初期文字列", 50);

引数を指定しない(①)場合、16文字分のメモリを確保したStringBuiderオブジェクトが作成されます。つまり16文字を超えるまでは新しくオブジェクトを作成する処理が起きないというわけですね。

格納する文字列の最大文字数がある程度わかっている場合は、引数に文字数を指定するとより効率が良くなります(②)。「将来120文字くらいの文字列が入る可能性があるから123文字分用意しておこう」といった感じですね。

引数に文字列を指定する(③)場合、その文字列を格納した状態のStringBuidlerが作成できます。

そして②と③を合わせたような形として、引数に初期文字列と初期メモリ確保量を指定する(④)こともできます。

String型にの変換:ToString()

StringBuilderオブジェクトは当然のことながらString型オブジェクトではありません。

String型オブジェクトへ変換するためにはToString()メソッドを使います。

StringBuilder sb = new StringBuilder("こんにちは!");

// String型に変換
string message = sb.ToString();

Console.WriteLine(message);

こんにちは!

文字列の結合:Insert() , Append()

文字列の結合は、Insert()メソッドもしくはAppend()メソッドを使います。

Insert()・・・特定の場所に文字列を追加したいとき

Append()・・・末尾に文字列を追加したいとき

StringBuilder sb = new StringBuilder();

// Insert()
sb.Insert(0, "先頭に追加!");

// Append()
sb.Append("末尾に追加!");

Console.WriteLine(sb.ToString());

先頭に追加!末尾に追加!

文字列の変換:Replace()

文字列の変換は、String型でもおなじみのReplase()メソッドを使います。

StringBuilder sb = new StringBuilder();
sb.Append("「変換前」の文字列");

// 文字列の変換
sb.Replace("変換前", "返還後");

Console.WriteLine(sb.ToString());

「変換後」の文字列

文字列の削除:Remove()

文字列を削除は、Remove()メソッドを使います。

第1引数に開始番号(0始まり)を指定し、第二引数に何文字分を削除するのかを指定します。

StringBuilder sb = new StringBuilder();
sb.Append("「変換前」の文字列");

// 文字列の削除
sb.Remove(0, 6);

Console.WriteLine(sb.ToString());

文字列

現状確保しているメモリ量(文字数):Capacity

あまり使う機会は少ないかもですが、現状確保しているメモリ量を確認する場合は、Capacityプロパティを使います。

StringBuilder sb = new StringBuilder();

// 現在のメモリ確保量
Console.WriteLine(sb.Capacity);

16

上の例で分かる通り、引数無しでStringBuilderオブジェクトを作成すると、16文字分のメモリが確保されます。

StringBuilder型オブジェクトのメモリ確保量(Capacity)は「増えるが減らない」!

StringBuilder型オブジェクトのメモリ確保量(Capacity)は、最小で「16」であり、文字数が16文字よりも大きい場合にその文字数分のメモリが確保されます

// 16文字分 確保
StringBuilder sb = new StringBuilder();

// 16文字分より少なくても16文字分 確保
StringBuilder sb_01 = new StringBuilder("あいう");

// 20文字分 確保される
ab.Applend("あいうえおあいうえおあいうえおあいうえお");

対して、Remove()やReplace()で削除・変換して文字数が少なくなった場合は、メモリの確保量が減りません

// 16文字分 確保
StringBuilder sb = new StringBuilder();

// 16文字分より少なくても16文字分 確保
StringBuilder sb_01 = new StringBuilder("あいう");

// 20文字分 確保される
ab.Applend("あいうえおあいうえおあいうえおあいうえお");

// 20文字分 確保されたまま
ab.Remove(0, 10);

まとめ

  • 文字列を頻繁に処理(結合や削除、変換など)する場合は、String型ではなくStringBuilder型を使おう!
  • Insert()で任意の場所に追加、Append()で末尾に追加。
  • Remove()で任意の部分を削除、Replace()で任意の文字を変換。
  • 現状確保しているメモリ量(文字数)はCapacityプロパティで取得。
  • 確保しているメモリ量は「増えるが減らない」。

ぜひStringBuilder型を使いこなして、効率の良いプログラミングをしてみてくださいね!


参考:https://learn.microsoft.com/ja-jp/dotnet/api/system.text.stringbuilder?view=net-8.0

コメント