StringBuilder を使用して文字列を連結する方が高速であると誰かが私に言いました。コードを変更しましたが、最終的なビルド文字列を取得するためのプロパティまたはメソッドが表示されません。
どうすれば文字列を取得できますか?
StringBuilder を使用して文字列を連結する方が高速であると誰かが私に言いました。コードを変更しましたが、最終的なビルド文字列を取得するためのプロパティまたはメソッドが表示されません。
どうすれば文字列を取得できますか?
から.ToString()
を取得するために使用できます。String
StringBuilder
「String を String ビルダーと連結する方が速い」と言うとき、これは同じオブジェクトに繰り返し(繰り返します -繰り返し) 連結している場合にのみ当てはまります。
2 つの文字列を連結し、その結果をすぐに として処理するstring
場合、 を使用しても意味がありませんStringBuilder
。
私は、Jon Skeet の素晴らしい記事を見つけました: http://www.yoda.arachsys.com/csharp/stringbuilder.html
を使用している場合StringBuilder
、結果の を取得するには、 (当然string
のことながら) を呼び出すだけToString()
です。
StringBuilder を使用した処理が完了したら、ToString メソッドを使用して最終結果を返します。
MSDN から:
using System;
using System.Text;
public sealed class App
{
static void Main()
{
// Create a StringBuilder that expects to hold 50 characters.
// Initialize the StringBuilder with "ABC".
StringBuilder sb = new StringBuilder("ABC", 50);
// Append three characters (D, E, and F) to the end of the StringBuilder.
sb.Append(new char[] { 'D', 'E', 'F' });
// Append a format string to the end of the StringBuilder.
sb.AppendFormat("GHI{0}{1}", 'J', 'k');
// Display the number of characters in the StringBuilder and its string.
Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString());
// Insert a string at the beginning of the StringBuilder.
sb.Insert(0, "Alphabet: ");
// Replace all lowercase k's with uppercase K's.
sb.Replace('k', 'K');
// Display the number of characters in the StringBuilder and its string.
Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString());
}
}
// This code produces the following output.
//
// 11 chars: ABCDEFGHIJk
// 21 chars: Alphabet: ABCDEFGHIJK
必ずしも高速であるとは限らないことを捨てたいと思います。メモリフットプリントは間違いなく優れています。これは、.NET では文字列が不変であり、文字列を変更するたびに新しい文字列が作成されるためです。
より高速/より良いメモリであることについて:
私は Java でこの問題を調べましたが、.NET も同様に優れていると思います。
String の実装は非常に印象的です。
String オブジェクトは、「長さ」と「共有」を追跡します (文字列を保持する配列の長さとは無関係です)。
だから何か
String a = "abc" + "def" + "ghi";
次のように (コンパイラ/ランタイムによって) 実装できます。
- 「abc」を保持する配列を 6 つの追加スペースで拡張します。 - abcの直後にdefをコピー - def の後に ghi をコピーします。 - 「abc」文字列へのポインタを - abc の長さを 3 のままにし、a の長さを 9 に設定します。 - 両方で共有フラグを設定します。
ほとんどの文字列は寿命が短いため、多くの場合、非常に効率的なコードになります。絶対に効率的ではない場合は、ループ内で文字列に追加する場合、またはコードが次のような場合です。
a = "abc";
a = a + "def";
a += "ghi";
この場合、StringBuilder コンストラクトを使用する方がはるかに優れています。
私のポイントは、最適化するときはいつでも注意する必要があるということです。ただし、自分が何をしているのかを完全に理解しており、かつそれが必要であると絶対に確信しており、最適化されたコードがユースケースをパスすることを確認するためにテストし、コーディングするだけです。可能な限り最も読みやすい方法で、コンパイラーの裏をかこうとしないでください。
文字列をいじったり、文字列ビルダーをキャッシュ/再利用したり、速度をテストしたりして 3 日間無駄にしました。それから、自分が何をしているのか本当にわかっていなかったのかを説明しなければなりませんでした。
連結する方が速くない - smaclell が指摘したように、問題は不変の文字列が余分な割り当てを強制し、既存のデータを再コピーすることです。
"a"+"b"+"c" は、文字列ビルダーを使用しても高速ではありませんが、中間文字列との連結の繰り返しは、次のように連結の数が大きくなるにつれて、ますます高速になります。
x = "a"; x+="b"; x+="c"; ...