6

このコードはどうかと思います...

StringBuilder sb = new StringBuilder("Please read the following messages.");

...sbコンストラクターに渡された文字列とまったく同じ大きさのバッファーで初期化します。一方で、これは最も論理的なことのように思えます。一方で、StringBuilderクラスの最も一般的な用途の 1 つであるクラスの目的、つまり繰り返し追加をより効率的にするための可変性を提供するという目的に反しているように見えます。Append(私の質問に対する答えが「はい」の場合、への最初の呼び出しは、sbそれ自体のサイズを変更する必要があります。)

もう一度言いますが、これは をパラメーターとしてList<T>取るコンストラクターに類似していると見なすことができると思いIEnumerable<T>ます。おそらく、この場合の前提は、多くの追加を計画しているのではなく、既に存在するものを操作することを計画しているということです。

これについて私が行った唯一の実際の調査は、 StringBuilder に関する MSDN ドキュメントを確認することでしたが、これは答えを提供しませんでした (コンストラクターが「指定された文字列を使用して」インスタンスを初期化すると述べていますが、文字列がどのように機能するかは示していません)。使用済み)。


編集:それは「実装固有」です...これは他の誰にも奇妙に見えませんか?つまり、クラスの目的は、 で多くの操作を実行する代わりに、途中で大量の不変インスタンスを作成するStringBuilder代替手段を提供することです。したがって、効率のためです。プラットフォームに関係なく、開発者が情報に基づいて使用方法を決定できるように、このコンストラクターの動作を指定する必要があると思います。stringstring

つまり、Microsoft によって特定の方法で実装されています。彼らはそれをドキュメントに簡単に入れることができたでしょう(他の実装に追随を強いる)。困惑の個人的なソース...

4

4 に答える 4

5

これは、気にする必要のない実装の詳細です。ただし、.NET Reflectorを使用し、コンストラクターの (string,int32,int32,int32) オーバーロード (他のコンストラクターが呼び出す) を調べると、16 の倍数 (2 番目に大きい) の容量が選択されていることがわかります。要求されたサイズ)

編集

実際には、16 x 2^n で、「n」の値が次に大きいサイズとして選択されています

于 2010-02-15T13:58:03.463 に答える
4

StringBuilder の Capacity メンバを確認してください。

MSDNから:

StringBuilder は、必要に応じてより多くのスペースを動的に割り当て、それに応じて容量を増やします。パフォーマンス上の理由から、StringBuilder は必要以上のメモリを割り当てる場合があります。割り当てられるメモリの量は実装固有です。

于 2010-02-15T13:56:49.197 に答える
2

リンクしたコンストラクターは、おそらく次のようにチェーンされていStringBuilder(String, Int32, Int32, Int32)ます。

public StringBuilder(
  string value,
  int startIndex,
  int length,
  int capacity
)

したがって、文字列の場合、おそらく文字列、0、文字列.長さ、文字列.長さを通過します。または、StringBuilder コンテキストで意味のある類似のもの。

于 2010-02-15T13:58:31.627 に答える
1

最終的に呼び出されるコンストラクタは次のとおりです。

// "Please read the following messages.".Length = 35
public StringBuilder(string value, int startIndex, int length, int capacity)
public StringBuilder("Please read the following messages.", 0, 
        "Please read the following messages.".Length, 16)

(これは他の回答が提供しないものではなく、リフレクターからのものです)
容量が文字列の長さよりも小さい場合、この場合は次のとおりです。

while (capacity < length)
{
    capacity *= 2;
    if (capacity < 0)
    {
        capacity = length;
        break;
    }
}

Mono では、StringBuilder(string val)コンストラクターは追加が発生するまで容量を int.MaxValue に割り当てます。

本当の答えは、CLR で内部的に呼び出されるメソッドにあります。ここで、長さは容量です。

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string FastAllocateString(int length);

SSCLIでこれのソースが見つかりませんが、Mono バージョン (\mono\metadata\object.c) では次のようになります。

mono_string_new_size (MonoDomain *domain, gint32 len)
{
    MonoString *s;
    MonoVTable *vtable;
    size_t size = (sizeof (MonoString) + ((len + 1) * 2));

...
}

これは、MonoString オブジェクトのバイト単位のサイズに長さの 2 を加えたものです。

于 2010-02-15T14:24:39.407 に答える