次の方法で共有


StringBuilder.Append オーバーロードと評価順序

C# 10 では、文字列に加えてカスタムの "ハンドラー" を対象とする機能など、 より適切な文字列補間のサポートが追加されています。 StringBuilder は、カスタム補間文字列ハンドラーを受け入れる AppendAppendLine の新しいオーバーロードでこれを利用します。 これらのメソッドに対する既存の呼び出しでは、新しいオーバーロードへのバインディングが開始される可能性があります。 一般に、動作は同じですが、パフォーマンスが向上します。 たとえば、最初に文字列を作成してからその文字列を追加するのではなく、挿入された文字列の各コンポーネントが直接ビルダーに追加されます。 ただし、これにより、書式項目として使用されるオブジェクトの評価順序が変更される可能性があり、動作の違いとして現れる可能性があります。

以前の動作

以前のバージョンでは、次の呼び出しは、

stringBuilder.Append($"{a} {b}");

次と同等にコンパイルされます。

stringBuilder.Append(string.Format("{0} {1}", a, b));

つまり、 a が評価され、 b が評価された後、それらの評価の結果から文字列が作成され、その文字列がビルダーに追加されます。

新しい動作

.NET 6 以降では、次の呼び出しは、

stringBuilder.Append($"{a} {b}");

次と同等にコンパイルされます。

var handler = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder);
handler.AppendFormatted(a);
handler.AppendLiteral(" ");
handler.AppendFormatted(b);
stringBuilder.Append(ref handler);

つまり、 a が評価され、ビルダーに追加された後、 b が評価され、ビルダーに追加されます。

たとえば、次のコードに示すように、 a または b 自体がビルダーである場合、新しい評価順序によって実行時に異なる動作が発生する可能性があります。

stringBuilder.Append($"{a} {stringBuilder}");

導入されたバージョン

6.0 RC 1

破壊的変更の種類

この変更は ソースの互換性に影響を与える可能性があります。

変更の理由

開発者は、文字列を手動で分割して各部分のStringBuilderを呼び出すよりも便利であるため、補間文字列をStringBuilder.Appendに渡すのが一般的です。 これらの新しいオーバーロードにより、簡潔な構文と、個々の呼び出しのほとんどのパフォーマンスが有効になります。

StringBuilder.AppendStringBuilder.AppendLineが使用されるほとんどの場合、機能的な違いは見られません。 問題となる違いが判明した場合は、挿入文字列の前に(string)にキャストを追加することで、以前の動作を復元できます。 例えば次が挙げられます。

stringBuilder.Append((string)$"{a} {b}")

ただし、互換性のために実際に必要な場合を除き、これはお勧めしません。

影響を受ける API

こちらも参照ください