Como não acho que as respostas aqui abranjam tudo, gostaria de fazer uma pequena adição aqui.
Console.WriteLine(string format, params object[] pars)
chamadas string.Format
. O '+' implica concatenação de string. Eu não acho que isso sempre tenha a ver com estilo; Eu costumo misturar os dois estilos, dependendo do contexto em que estou.
Resposta curta
A decisão que você está enfrentando tem a ver com a alocação de string. Vou tentar simplificar.
Diga que você tem
string s = a + "foo" + b;
Se você executar isso, ele avaliará da seguinte maneira:
string tmp1 = a;
string tmp2 = "foo"
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);
tmp
aqui não é realmente uma variável local, mas é temporária para o JIT (é empurrada na pilha IL). Se você pressionar uma string na pilha (como ldstr
em IL para literais), você colocará uma referência a um ponteiro de string na pilha.
O momento em que você chama concat
essa referência se torna um problema, porque não há nenhuma referência de string disponível que contenha as duas strings. Isso significa que o .NET precisa alocar um novo bloco de memória e preenchê-lo com as duas seqüências de caracteres. A razão pela qual isso é um problema é porque a alocação é relativamente cara.
O que muda a pergunta para: Como você pode reduzir o número de concat
operações?
Portanto, a resposta aproximada é: string.Format
para> 1 concats, '+' funcionará bem para 1 concat. E se você não se importa em fazer otimizações de micro-desempenho, string.Format
funcionará bem no caso geral.
Uma nota sobre Cultura
E depois há algo chamado cultura ...
string.Format
permite usar CultureInfo
na sua formatação. Um operador simples '+' usa a cultura atual.
Esta é uma observação especialmente importante se você estiver escrevendo formatos de arquivo e f.ex. double
valores que você 'adiciona' a uma sequência. Em máquinas diferentes, você pode acabar com cadeias diferentes se não usar string.Format
com um explícito CultureInfo
.
F.ex. considere o que acontece se você alterar um '.' para um ',' enquanto escreve seu arquivo de valores separados por vírgula ... em holandês, o separador decimal é uma vírgula; portanto, o usuário pode ter uma surpresa 'engraçada'.
Resposta mais detalhada
Se você não souber o tamanho exato da string de antemão, é melhor usar uma política como essa para generalizar os buffers que você usa. O espaço livre é preenchido primeiro, após o qual os dados são copiados.
Crescer significa alocar um novo bloco de memória e copiar os dados antigos para o novo buffer. O antigo bloco de memória pode ser liberado. Você obtém os resultados neste ponto: crescer é uma operação cara.
A maneira mais prática de fazer isso é usar uma política de alocação geral. A política mais comum é alocar buffers em potências de 2. É claro que você precisa fazê-lo um pouco mais inteligente do que isso (já que não faz sentido aumentar de 1,2,4,8 se você já sabe que precisa de 128 caracteres ) mas você entendeu. A política garante que você não precise de muitas das operações caras que descrevi acima.
StringBuilder
é uma classe que basicamente aloca o buffer subjacente em potências de dois. string.Format
usa StringBuilder
sob o capô.
Isso faz da sua decisão uma troca básica entre atribuir globalmente e acrescentar (múltiplos) (com duas culturas) ou apenas alocar e acrescentar.
string.Format
que não usa nenhum recurso de formatação composta (isto é, simples{0}
) e substitui-os pela concatenação de cadeias consideravelmente mais rápida. Gostaria de saber que tal feito é possível com um reescritor de IL existente, como o PostSharp.