質問

メソッドでStringBuilderオブジェクトを使用して文字列を作成している場合、次のことが意味をなします:

StringBuilderオブジェクトを返し、呼び出し元のコードがToString()を呼び出すようにしますか?

return sb;

OR ToString()を自分で呼び出して文字列を返します。

return sb.ToString();

小さな文字列または大きな文字列を返す場合、違いが生じると思います。それぞれの場合に適切なものは何ですか?事前に感謝します。

編集: 呼び出し元のコードの文字列をさらに変更する予定はありませんが、良い点はコリンバーネットです。

主に、StringBuilderオブジェクトまたは文字列を返す方が効率的ですか?文字列への参照が返されますか、それともコピーですか?

役に立ちましたか?

解決

さらに文字列を変更する場合はStringBuilderを返し、そうでない場合は文字列を返します。これはAPIの質問です。

効率について。これは、詳細のない漠然とした/一般的な質問なので、パフォーマンスよりも可変対不変の方が重要だと思います。可変性は、APIが変更可能なオブジェクトを返すようにするというAPIの問題です。文字列の長さはこれとは無関係です。

それは言った。 ReflectorでStringBuilder.ToStringを見ると:

public override string ToString()
{
    string stringValue = this.m_StringValue;
    if (this.m_currentThread != Thread.InternalGetCurrentThread())
    {
        return string.InternalCopy(stringValue);
    }
    if ((2 * stringValue.Length) < stringValue.ArrayLength)
    {
        return string.InternalCopy(stringValue);
    }
    stringValue.ClearPostNullChar();
    this.m_currentThread = IntPtr.Zero;
    return stringValue;
}

あなたはそれがコピーを作成するかもしれないが、StringBuilderでそれを変更すると、それからコピーを作成することがわかります(これはmendがこれをチェックし、それが現在のスレッド)。

これで終わりは、StringBuilderを変更しない場合、文字列をコピーせず、長さが効率に関係ないことです(2番目のifをヒットしない限り)。

更新

System.Stringはクラスであるため、(値型ではなく)参照型であるため、&quot; string foo;&quot;本質的にポインタです。 (文字列をメソッドに渡すと、コピーではなくポインタが渡されます。)System.Stringはmscorlib内では可変ですが、外部では不変です。これがStringBuilderが文字列を操作する方法です。

ToString()が呼び出されると、参照によって内部文字列オブジェクトを返します。コードはmscorlibにないため、この時点では変更できません。 m_currentThreadフィールドをゼロに設定すると、StringBuilderでさらに操作を行うと、文字列オブジェクトがコピーされるため、ToString()で返された文字列オブジェクトを変更することができます。これを考慮してください:

StringBuilder sb = new StringBuilder();
sb.Append("Hello ");

string foo = sb.ToString();

sb.Append("World");

string bar = sb.ToString();

StringBuilderがコピーを作成しなかった場合、最後のfooは&quot; Hello World&quot;になります。 StringBuilderが変更したためです。しかし、コピーを作成したので、fooはまだ&quot; Hello&quot;のままです。バーは&quot; Hello World&quot;です。

これにより、返品/参照全体が明確になりますか?

他のヒント

パフォーマンスがこの問題の要因になるとは思わない。いずれにせよ、誰かがsb.ToString()を呼び出して、どこかでヒットするようにします。

より重要な質問は、メソッドの目的と目的は何かということです。このメソッドがビルダーの一部である場合、文字列ビルダーを返すことがあります。そうでなければ、文字列を返します。

これがパブリックAPIの一部である場合、ビルダーではなく文字列を返すようになります。

メソッドはsb.ToString()を返すべきだと思います。 StringBuilder()オブジェクトの作成を取り巻くロジックが将来変更される場合、メソッドを呼び出してから他のことを行う各シナリオではなく、メソッドで変更されることは理にかなっています

StringBuilder は、メソッドの実装の詳細です。パフォーマンスの問題になるまで文字列を返す必要があります。その時点で、別のパターン(訪問者パターン)間接性を導入し、内部実装の決定から保護するのに役立ちます。

文字列は常にヒープに格納されるため、戻り値の型が文字列の場合、参照が返されます。ただし、2つの同一の文字列が同一の参照を持つとは考えられません。一般に、実際には参照型であるにもかかわらず、文字列を値型であると考えるのが安全です。

文字列がメソッドを出ると、文字列で何をしているのかによります。追加を続ける場合は、効率を高めるために文字列ビルダーを返すことを検討してください。常に.ToString()を呼び出す場合は、カプセル化を改善するためにメソッド内で行う必要があります。

ほとんどすべての状況で、特にメソッドがパブリックAPIの一部である場合、 string を返します。

例外は、メソッドがより大きなプライベートな「ビルダー」の一部にすぎない場合です。プロセスと呼び出しコードはさらに操作を行います。その場合、 StringBuilder を返すことを検討します。

もう変更しないので

return sb.ToString();

最も効率的でなければなりません

sb.ToString()を返します。メソッドは、手元にあるもの(この場合は文字列を作成します)に集中し、IMOをさらに操作するために返されないようにする必要があります。

これは、出力をどのように処理するかによって異なります。私は個人的に文字列を返します。そうすれば、メソッドを文字列ビルダーを使用しないように変更する必要がある場合は、戻り値としてそれで立ち往生することはありません。

今のところ考えてみると、答えはずっと明確です。返すべき質問は本当に質問に答えます。返されるオブジェクトは文字列でなければなりません。理由は、質問をしている場合、「文字列が実行されるときにStringBuilderオブジェクトを返す理由はありますか?」答えはノーです。理由がある場合、stringbuilderのメソッドとプロパティが必要なので、文字列を返すことは問題外です。

より多くのものを文字列に追加し、他の文字列ビルダー関連機能を使用する必要がある場合は、文字列ビルダーを返します。それ以外の場合、文字列自体を使用している場合は、文字列を返します。

他にも技術的な考慮事項がありますが、それは最高レベルの懸念です。

メソッドには具体的なタスクが与えられ、メソッドを完了し、さらに処理する必要のない最終結果を返すことが期待されます。本当に必要なときだけStringBuilderを返します。その場合、メソッド名に何かを追加して、何か特別なものを返すことを示します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top