StringBuilder.Append オーバーロードと評価順序
C# 10 では、文字列に加えてカスタムの "ハンドル" を対象とする機能など、文字列補間の改善がサポートされています。 StringBuilder では、カスタムの補完文字列ハンドラーを受け入れる Append と AppendLine の新しいオーバーロードで、これを利用します。 これらのメソッドに対する既存の呼び出しでは、新しいオーバーロードへのバインディングが開始される可能性があります。 通常、動作は同じですが、パフォーマンスが向上します。 たとえば、文字列が最初に作成され、その文字列が追加されるのではなく、補間された文字列の個々のコンポーネントがビルダーに直接追加されます。 ただし、これにより、書式項目として使用されるオブジェクトの評価順序が変更される可能性があり、動作の違いとして現れる可能性があります。
以前の動作
以前のバージョンでは、次の呼び出しは、
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.Append を呼び出すよりも便利であるため、開発者は補間された文字列を StringBuilder に渡すのが一般的です。 これらの新しいオーバーロードにより、構文が簡潔になり、個々の呼び出しを実行するパフォーマンスが向上します。
推奨アクション
StringBuilder.Append および StringBuilder.AppendLine を使用する場合、ほとんどの場合は機能に違いはありません。 違いによって問題が生じることが判明した場合は、補間された文字列の前に、(string)
へのキャストを追加することで、以前の動作を復元できます。 次に例を示します。
stringBuilder.Append((string)$"{a} {b}")
ただし、互換性のために実際に必要な場合を除いて、これはお勧めしません。
影響を受ける API
関連項目
.NET