Surcharges de stringBuilder.Append et ordre d’évaluation

C# 10 ajoute la prise en charge d’une meilleure interpolation de chaînes, notamment la possibilité de cibler des « gestionnaires » personnalisés en plus des chaînes. StringBuilder en tire parti avec de nouvelles surcharges de Append et AppendLine qui acceptent un gestionnaire de chaînes interpolées personnalisé. Les appels existants à ces méthodes peuvent maintenant commencer à être liés aux nouvelles surcharges. En général, le comportement est identique, mais avec des performances améliorées. Par exemple, plutôt que de créer d’abord une chaîne de caractères, puis d’ajouter cette chaîne, les composants individuels de la chaîne interpolée sont ajoutés directement au constructeur. Toutefois, cela peut modifier l’ordre d’évaluation des objets utilisés comme éléments de mise en forme, ce qui peut se manifester sous la forme d’une différence de comportement.

Comportement précédent

Dans les versions précédentes, un appel à :

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

compilait l’équivalent de :

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

Cela signifie que a est évalué, puis b est évalué, puis une chaîne est créée à partir des résultats de ces évaluations, et enfin cette chaîne est ajoutée au générateur.

Nouveau comportement

À partir de .NET 6, un appel à :

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

compile l’équivalent de :

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

Cela signifie que a est évalué et ajouté au générateur, puis b est évalué et ajouté au générateur.

Si, par exemple, a ou b est lui-même le générateur, comme indiqué dans le code suivant, le nouvel ordre d’évaluation peut entraîner un comportement différent au moment de l’exécution.

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

Version introduite

6.0 RC 1

Type de changement cassant

Ce changement peut affecter la compatibilité source.

Raison du changement

Il est courant pour les développeurs de passer des chaînes interpolées à StringBuilder, car cela est plus pratique que de fractionner manuellement la chaîne et d’appeler StringBuilder.Append pour chaque partie. Ces nouvelles surcharges permettent d’avoir une syntaxe concise et de conserver la majeure partie des performances de l’exécution des appels individuels.

Dans la plupart des cas où StringBuilder.Append et StringBuilder.AppendLine sont utilisés, vous ne remarquerez pas de différence fonctionnelle. Si vous remarquez une différence qui s’avère problématique, vous pouvez restaurer le comportement précédent en ajoutant un cast à (string) avant la chaîne interpolée. Par exemple :

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

Toutefois, cela n’est pas recommandé, sauf si cela est réellement requis à des fins de compatibilité.

API affectées

Voir aussi