Quantos objetos String serão criados ao usar um sinal de mais no código abaixo?
String result = "1" + "2" + "3" + "4";
Se fosse como abaixo, eu teria dito três objetos String: "1", "2", "12".
String result = "1" + "2";
Eu também sei que os objetos String são armazenados em cache no Pool / Table Intern de String para melhoria de desempenho, mas essa não é a questão.
Respostas:
Surpreendentemente, depende.
Se você fizer isso em um método:
então o compilador parece emitir o código usando
String.Concat
como @Joachim respondeu (+1 para ele aliás).Se você os definir como constantes , por exemplo:
ou como literais , como na pergunta original:
então o compilador irá otimizar esses
+
sinais. É equivalente a:Além disso, o compilador removerá expressões constantes estranhas e apenas as emitirá se forem usadas ou expostas. Por exemplo, este programa:
Gera apenas uma string - a constante
result
(igual a "1234").one
etwo
não aparecem no IL resultante.Lembre-se de que pode haver mais otimizações no tempo de execução. Estou apenas analisando o que o IL é produzido.
Finalmente, no que diz respeito ao internamento, constantes e literais são internados, mas o valor que é internado é o valor da constante resultante no IL, não o literal. Isso significa que você pode obter ainda menos objetos de string do que o esperado, já que várias constantes ou literais definidas de forma idêntica serão na verdade o mesmo objeto! Isso é ilustrado pelo seguinte:
No caso em que Strings são concatenadas em um loop (ou de outra forma dinamicamente), você acaba com uma string extra por concatenação. Por exemplo, o seguinte cria 12 instâncias de string: 2 constantes + 10 iterações, cada uma resultando em uma nova instância de String:
Mas (também surpreendentemente), várias concatenações consecutivas são combinadas pelo compilador em uma única concatenação multi-string. Por exemplo, este programa também produz apenas 12 instâncias de string! Isso ocorre porque " Mesmo se você usar vários operadores + em uma instrução, o conteúdo da string é copiado apenas uma vez. "
fonte
string s = ""; for (int i = 0; i < n; i++) s += "a";
A resposta de Chris Shain é muito boa. Como a pessoa que escreveu o otimizador de concatenação de string, eu acrescentaria apenas dois pontos interessantes adicionais.
A primeira é que o otimizador de concatenação essencialmente ignora os parênteses e a associatividade à esquerda quando pode fazer isso com segurança. Suponha que você tenha um método M () que retorna uma string. Se você diz:
então, o compilador raciocina que o operador de adição é associativo à esquerda e, portanto, é o mesmo que:
Mas isso:
é o mesmo que
então essa é a concatenação da string constante
"CD"
comM()
.Na verdade, o otimizador de concatenação percebe que a concatenação de string é associativa e gera
String.Concat(M(), "AB")
para o primeiro exemplo, embora isso viole a associatividade à esquerda.Você pode até fazer isso:
e ainda vamos gerar
String.Concat(M(), "EF", M())
.O segundo ponto interessante é que strings nulas e vazias são otimizadas. Então, se você fizer isso:
você terá
String.Concat(M(), M())
Surge então uma questão interessante: e quanto a isso?
Não podemos otimizar isso para
porque
M()
pode retornar nulo, masString.Concat(M(), null)
retornaria uma string vazia seM()
retornar nulo. Então, o que fazemos é reduzirpara
Demonstrando assim que a concatenação de string não precisa realmente ser chamada
String.Concat
.Para mais leituras sobre este assunto, consulte
Por que String.Concat não é otimizado para StringBuilder.Append?
fonte
("C" + "D") + M())
geraString.Concat("CD", M())
, nãoString.Concat(M(), "AB")
. E mais abaixo,(M() + "E") + (null + M())
deve gerarString.Concat(M(), "E", M())
, nãoString.Concat(M(), M())
.Eu encontrei a resposta no MSDN. 1.
How to: Concatenate Multiple Strings (C # Programming Guide)
fonte
Apenas um. O compilador C # dobrará constantes de string e, portanto, essencialmente compilará para
fonte
Duvido que isso seja exigido por qualquer padrão ou especificação. Uma versão provavelmente pode fazer algo diferente da outra.
fonte
Um, por serem estáticos, o compilador será capaz de otimizá-lo para uma única string em tempo de compilação.
Se fossem dinâmicos, teriam sido otimizados para uma única chamada para String.Concat (string, string, string, string) .
fonte