string
とStringBuilder
の違いは何ですか?
また、理解するためのいくつかの例は何でしょうか?
string
インスタンスは不変です。作成後に変更することはできません。文字列を変更するように見える操作は、代わりに新しいインスタンスを返します。
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の文字列操作関数を参照してください)。
mutable文字列が必要な場合(ピース単位で構築する場合や多くのことを変更する場合など)、StringBuilder
が必要です。これは、 can変更できます。これは、ほとんどの場合、パフォーマンスに影響します。可変文字列が必要な場合、代わりに通常の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のみが実際にそれを行うことができ、それを賭けないほうが良いと思います)。
文字列は不変です。つまり、文字列を作成しても、変更することはできません。むしろ、新しい値を保存する新しい文字列を作成します。文字列変数の値を大幅に変更する必要がある場合、これは非効率的です。
StringBuilderは、変更可能な文字列をシミュレートするために使用できるため、文字列を大幅に変更する必要がある場合に適しています。
ひも
値の継続的な変更が発生すると、パフォーマンスが低下します
スレッドセーフ
StringBuilder(可変ストリング)
ObjectIDGenerator を使用した多くの例を含むこのトピックに関する説明記事については、 this link を参照してください。
関連するStack Overflowの質問:C#で文字列が変更されない場合の文字列の可換性
文字列
Stringインスタンスは不変です。つまり、作成後に変更することはできません。 Stringに対して何らかの操作を実行すると、既存のインスタンス値を変更する代わりに、新しいインスタンスを返します(メモリに新しいインスタンスを作成します)。
StringBuilder
StringBuilderは可変です。つまり、StringBuilderで何らかの操作を実行すると、既存のインスタンス値が更新され、新しいインスタンスは作成されません。
StringBuilderは、複数のステップで文字列を構築する必要がある場合に役立ちます。
これを行う代わりに:
String x = "";
x += "first ";
x += "second ";
x += "third ";
あなたがやる
StringBuilder sb = new StringBuilder("");
sb.Append("first ");
sb.Append("second ");
sb.Append("third");
String x = sb.ToString();
最終的な効果は同じですが、StringBuilderはより少ないメモリを使用し、より高速に実行されます。 2つの連結である新しい文字列を作成する代わりに、チャンクを個別に作成し、最後にのみそれらを結合します。
StringBuilder Class documentation から:
Stringオブジェクトは不変です。 System.Stringクラスのメソッドのいずれかを使用するたびに、メモリ内に新しい文字列オブジェクトを作成します。これには、その新しいオブジェクト用のスペースの新しい割り当てが必要です。文字列を繰り返し変更する必要がある状況では、新しいStringオブジェクトの作成に関連するオーバーヘッドが高くなる可能性があります。 System.Text.StringBuilderクラスは、新しいオブジェクトを作成せずに文字列を変更する場合に使用できます。たとえば、StringBuilderクラスを使用すると、ループ内で多くの文字列を連結する際のパフォーマンスが向上します。
主な違い:
文字列は不変です。つまり、文字列をまったく変更できないということです。変更の結果は新しい文字列です。文字列に追加する予定の場合、これは効果的ではありません。
StringBuilderは可変です。任意の方法で変更でき、新しいインスタンスを作成する必要はありません。作業が完了すると、ToString()を呼び出して文字列を取得できます。
文字列はインターンに参加できます。これは、同じ内容の文字列が同じアドレスを持つ可能性があることを意味します。 StringBuilderはインターンできません。
文字列は、参照リテラルを持つことができる唯一のクラスです。
文字列は不変です。つまり、値を変更すると、古い値は破棄され、ヒープに新しい値が作成されますが、文字列ビルダーでは、新しい値を作成せずに既存の値を変更できます。
したがって、パフォーマンスの面ではString Builderは有益です。これは、必要以上にメモリ領域を占有しないためです。
System.Stringは可変オブジェクトです。つまり、作成後は変更できません。理解を深めるために、C#?でのstringとStringBuilderの違いを参照してください。
文字列は不変の型です。これは、文字列を互いに連結し始めるたびに、毎回新しい文字列を作成していることを意味します。これを何度も行うと、大量のヒープオーバーヘッドとメモリ不足のリスクが生じます。
StringBuilderインスタンスを使用して、同じインスタンスに文字列を追加し、そのインスタンスでToStringメソッドを呼び出したときに文字列を作成できます。
StringBuilderオブジェクトをインスタンス化するオーバーヘッドのため、Microsoftは、5〜10個を超える文字列の連結がある場合に使用すると便利だと述べています。
サンプルコードについては、こちらをご覧になることをお勧めします。
文字列(System.String)は、.NETフレームワーク内で定義された型です。 Stringクラスは変更できません。つまり、System.Stringインスタンスに対してアクションを実行するたびに、.NETコンパイラーは文字列の新しいインスタンスを作成します。この操作は開発者には見えません。
System.Text.StringBuilderは、可変文字列を表すクラスです。このクラスは、StringBuilderによってラップされたStringをユーザーが管理できるようにする便利なメソッドを提供します。すべての操作が同じStringBuilderインスタンスで行われていることに注意してください。
マイクロソフトでは、StringBuilderを使用することをお勧めします。StringBuilderはメモリ使用量の点でより効果的です。
また、Stringの連結の複雑さはO(N2)ですが、StringBufferの場合はO(N)です。
そのため、毎回多くの新しいオブジェクトが作成されるため、ループで連結を使用するとパフォーマンスの問題が発生する可能性があります。
文字列ビルダーとともに文字列を反復処理する場合は、Clone
メソッドを使用できます。オブジェクトを返すため、ToStringメソッドを使用して文字列に変換できます... :)