Sobrecargas e ordem de avaliação de StringBuilder.Append
O C# 10 adiciona suporte para interpolação aprimorada de cadeia de caracteres, incluindo a capacidade de direcionamento a "identificadores" personalizados além de cadeias de caracteres. StringBuilder aproveita isso com novas sobrecargas de Append e AppendLine que aceitam um identificador de cadeia de caracteres interpolada personalizado. As chamadas existentes a esses métodos agora podem começar a se associar às novas sobrecargas. Em geral, o comportamento é idêntico, mas com desempenho aprimorado. Por exemplo, em vez de uma cadeia de caracteres ser criada primeiro e depois ser acrescentada, os componentes individuais da cadeia de caracteres interpolada são acrescentados diretamente ao construtor. No entanto, isso pode alterar a ordem de avaliação de objetos usados como itens de formato, o que pode se manifestar como uma diferença de comportamento.
Comportamento anterior
Nas versões anteriores, uma chamada a:
stringBuilder.Append($"{a} {b}");
era compilada com o equivalente a:
stringBuilder.Append(string.Format("{0} {1}", a, b));
Isso significa que a
é avaliado, depois b
é avaliado, uma cadeia de caracteres é criada com os resultados dessas avaliações e depois essa cadeia de caracteres é acrescentada ao construtor.
Novo comportamento
Do .NET 6 em diante, uma chamada a:
stringBuilder.Append($"{a} {b}");
é compilada para o equivalente a:
var handler = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder);
handler.AppendFormatted(a);
handler.AppendLiteral(" ");
handler.AppendFormatted(b);
stringBuilder.Append(ref handler);
Isso significa que a
é avaliado e acrescentado ao construtor e depois b
é avaliado e acrescentado ao construtor.
Se, por exemplo, a
ou b
for o construtor, conforme mostrado no código a seguir, a nova ordem de avaliação poderá resultar em comportamento diferente em tempo de execução.
stringBuilder.Append($"{a} {stringBuilder}");
Versão introduzida
6.0 RC 1
Tipo de alteração interruptiva
Essa alteração pode afetar a compatibilidade da origem.
Motivo da alteração
É comum que os desenvolvedores passem cadeias de caracteres interpoladas para StringBuilder, pois é mais conveniente do que dividir manualmente a cadeia de caracteres e chamar StringBuilder.Append para cada parte. Essas novas sobrecargas permitem uma sintaxe concisa e a maior parte do desempenho de fazer as chamadas individuais.
Ação recomendada
Na maioria dos casos em que StringBuilder.Append e StringBuilder.AppendLine são usados, você não observará uma diferença funcional. Se você encontrar uma diferença que se mostre problemática, restaure o comportamento anterior adicionando uma conversão a (string)
antes da cadeia de caracteres interpolada. Por exemplo:
stringBuilder.Append((string)$"{a} {b}")
No entanto, isso não é recomendado, a menos que seja realmente necessário por motivo de compatibilidade.