1. ホーム
  2. c#

C#の文字列とStringBuilderの違い

2023-12-27 13:42:28

疑問点

の違いは何ですか? stringStringBuilder ?

また、理解のための例としては何があるでしょうか?

どのように解決するのですか?

A string のインスタンスは immutable です。作成された後にそれを変更することはできません。文字列を変更するように見える操作は、代わりに新しいインスタンスを返します。

string foo = "Foo";
// returns a new string instance instead of changing the old one
string bar = foo.Replace('o', 'a');
string baz = foo + "bar"; // ditto here

例えば、同期の問題を心配することなくスレッド間で使用することができたり、変更すべきでないオブジェクトを誰かが変更することを恐れることなく、単純にプライベートなバッキングフィールドを直接渡すことができたりします(配列やミュータブルリストを参照してください、これらは望まない場合はそれらを返す前にコピーする必要があります)。しかし、不用意に使用すると、深刻なパフォーマンスの問題を引き起こす可能性があります (ほとんど何でもそうですが、実行速度を誇る言語の例が必要なら、C の文字列操作関数を見てみてください)。

を必要とするとき ミュータブル 文字列が必要な場合、例えば、断片的に構成されているものや、多くのものを変更するような場合、そのような文字列には StringBuilder という文字列のバッファが必要です。 が可能です。 を変更することができます。これは、ほとんどの場合、パフォーマンスに影響を及ぼします。もし、ミュータブルな文字列が欲しくて、その代わりに通常の string インスタンスで行う場合、不必要に多くのオブジェクトを作成したり破壊したりすることになります。 StringBuilder のインスタンスはそれ自体が変化するので、多くの新しいオブジェクトの必要性を否定します。

簡単な例です。次の例は、多くのプログラマが苦痛で身震いすることでしょう。

string s = string.Empty;
for (i = 0; i < 1000; i++) {
  s += i.ToString() + " ";
}

ここでは結局2001個の文字列が作成され、そのうち2000個は捨てられてしまいます。StringBuilderを使った同じ例です。

StringBuilder sb = new StringBuilder();
for (i = 0; i < 1000; i++) {
  sb.Append(i);
  sb.Append(' ');
}

これにより、メモリアロケータへの負荷がかなり軽減されるはずです :-)

しかし、C#コンパイラは文字列に関してはそれなりに賢いことに注意する必要があります。たとえば、次の行は

string foo = "abc" + "def" + "efg" + "hij";

はコンパイラによって結合され、実行時には一つの文字列だけが残ります。同様に、次のような行も

string foo = a + b + c + d + e + f;

は次のように書き換えられます。

string foo = string.Concat(a, b, c, d, e, f);

というように、5つの無意味な連結のためにお金を払う必要はありません。これは、上記のようなループでは保存されません(コンパイラがループを展開しない限り、JITだけが実際にそうするかもしれないと思うので、それに賭けない方がよいでしょう)。