Pergunta

Qual é a maneira mais eficiente de concatenar strings?

Foi útil?

Solução

O StringBuilder.Append() método é muito melhor do que usar o operador +.Mas descobri que, ao executar 1.000 concatenações ou menos, String.Join() é ainda mais eficiente do que StringBuilder.

StringBuilder sb = new StringBuilder();
sb.Append(someString);

O único problema com String.Join é que você precisa concatenar as strings com um delimitador comum.(Editar:) como @ryanversaw apontou, você pode criar o delimitador string.Empty.

string key = String.Join("_", new String[] 
{ "Customers_Contacts", customerID, database, SessionID });

Outras dicas

Rico Mariani, o guru do desempenho do .NET, tinha um artigo sobre este mesmo assunto.Não é tão simples como se poderia suspeitar.O conselho básico é este:

Se o seu padrão for semelhante a:

x = f1(...) + f2(...) + f3(...) + f4(...)

essa é uma concat e é rápida, o StringBuilder provavelmente não ajudará.

Se o seu padrão for semelhante a:

if (...) x += f1(...)
if (...) x += f2(...)
if (...) x += f3(...)
if (...) x += f4(...)

então você provavelmente deseja o StringBuilder.

Mais um artigo para apoiar esta afirmação vem de Eric Lippert onde ele descreve as otimizações realizadas em uma linha + concatenações de maneira detalhada.

Existem 6 tipos de concatenações de strings:

  1. Usando o sinal de mais (+) símbolo.
  2. Usando string.Concat().
  3. Usando string.Join().
  4. Usando string.Format().
  5. Usando string.Append().
  6. Usando StringBuilder.

Em um experimento, foi provado que string.Concat() é a melhor maneira de abordar se as palavras forem menores que 1000 (aproximadamente) e se as palavras forem maiores que 1000 então StringBuilder deve ser usado.

Para mais informações, verifique isto site.

string.Join() vs string.Concat()

O método string.Concat aqui é equivalente à invocação do método string.Join com um separador vazio.Acrescentar uma string vazia é rápido, mas não fazer isso é ainda mais rápido, então o string.Concat método seria superior aqui.

De Chinh Do - StringBuilder nem sempre é mais rápido:

Regras de ouro

  • Ao concatenar três valores de string dinâmicos ou menos, use a concatenação de string tradicional.

  • Ao concatenar mais de três valores de string dinâmicos, use StringBuilder.

  • Ao construir uma string grande a partir de vários literais de string, use o literal de string @ ou o operador inline +.

Maioria na maioria das vezes, StringBuilder é sua melhor aposta, mas há casos como mostrado naquele post em que você deve pelo menos pensar em cada situação.

Se você estiver operando em loop, StringBuilder é provavelmente a melhor opção;isso evita a sobrecarga de criar novas strings regularmente.No entanto, em código que será executado apenas uma vez, String.Concat provavelmente está bem.

No entanto, Rico Mariani (guru de otimização .NET) inventei um quiz no qual afirmou ao final que, na maioria dos casos, recomenda String.Format.

Aqui está o método mais rápido que desenvolvi ao longo de uma década para meu aplicativo de PNL em grande escala.tenho variações para IEnumerable<T> e outros tipos de entrada, com e sem separadores de diferentes tipos (Char, String), mas aqui mostro o caso simples de concatenando todas as strings em um array em uma única string, sem separador.A versão mais recente aqui foi desenvolvida e testada em unidade em C#7 e .NET 4.7.

Existem duas chaves para um desempenho superior;a primeira é pré-calcular o tamanho total exato necessário.Esta etapa é trivial quando a entrada é um array conforme mostrado aqui.Para manuseio IEnumerable<T> em vez disso, vale a pena primeiro reunir as strings em um array temporário para calcular esse total (o array é necessário para evitar chamar ToString() mais de uma vez por elemento, pois tecnicamente, dada a possibilidade de efeitos colaterais, isso poderia alterar a semântica esperada de uma operação de 'junção de string').

Em seguida, dado o tamanho total da alocação da string final, o maior impulso no desempenho é obtido por construindo a string de resultado no local.Fazer isto requer a técnica (talvez controversa) de suspender temporariamente a imutabilidade de um novo String que é inicialmente alocado cheio de zeros.Qualquer controvérsia à parte, no entanto...

...observe que esta é a única solução de concatenação em massa nesta página que evita totalmente um rodada extra de alocação e cópia pelo String construtor.

Código completo:

/// <summary>
/// Concatenate the strings in 'rg', none of which may be null, into a single String.
/// </summary>
public static unsafe String StringJoin(this String[] rg)
{
    int i;
    if (rg == null || (i = rg.Length) == 0)
        return String.Empty;

    if (i == 1)
        return rg[0];

    String s, t;
    int cch = 0;
    do
        cch += rg[--i].Length;
    while (i > 0);
    if (cch == 0)
        return String.Empty;

    i = rg.Length;
    fixed (Char* _p = (s = new String(default(Char), cch)))
    {
        Char* pDst = _p + cch;
        do
            if ((t = rg[--i]).Length > 0)
                fixed (Char* pSrc = t)
                    memcpy(pDst -= t.Length, pSrc, (UIntPtr)(t.Length << 1));
        while (pDst > _p);
    }
    return s;
}

[DllImport("MSVCR120_CLR0400", CallingConvention = CallingConvention.Cdecl)]
static extern unsafe void* memcpy(void* dest, void* src, UIntPtr cb);

Devo mencionar que este código tem uma ligeira modificação em relação ao que eu mesmo uso.No original, eu Ligar para cpblk Instrução IL de C# para fazer a cópia real.Para simplicidade e portabilidade do código aqui, substituí-o por P/Invoke memcpy em vez disso, como você pode ver.Para maior desempenho em x64 (mas talvez não x86) você pode querer usar o cpblk método em vez disso.

A partir disso Artigo MSDN:

Há algumas despesas gerais associadas à criação de um objeto StringBuilder, tanto no tempo quanto na memória.Em uma máquina com memória rápida, um StringBuilder fica a pena se você estiver fazendo cerca de cinco operações.Como regra geral, eu diria que 10 ou mais operações de cordas é uma justificativa para a sobrecarga em qualquer máquina, mesmo mais lenta.

Portanto, se você confia no MSDN, use o StringBuilder se precisar executar mais de 10 operações/concatenações de strings - caso contrário, uma concatenação de string simples com '+' é adequada.

Somando-se às outras respostas, lembre-se de que StringBuilder pode receber uma quantidade inicial de memória para alocar.

O capacidade O parâmetro define o número máximo de caracteres que podem ser armazenados na memória alocada pela instância atual.Seu valor é atribuído ao Capacidade propriedade.Se o número de caracteres a serem armazenados na instância atual exceder este capacidade valor, o objeto StringBuilder aloca memória adicional para armazená-los.

Se capacidade for zero, a capacidade padrão específica da implementação será usada.

Anexar repetidamente a um StringBuilder que não foi pré-alocado pode resultar em muitas alocações desnecessárias, assim como concatenar repetidamente strings regulares.

Se você sabe quanto tempo a string final terá, pode calculá-la trivialmente ou pode fazer uma estimativa fundamentada sobre o caso comum (alocar muito não é necessariamente uma coisa ruim), você deve fornecer essas informações ao construtor ou ao Capacidade propriedade. Especialmente ao executar testes de desempenho para comparar StringBuilder com outros métodos como String.Concat, que fazem a mesma coisa internamente.Qualquer teste que você vê on-line que não inclua a pré-alocação do StringBuilder em suas comparações está errado.

Se você não consegue adivinhar o tamanho, provavelmente está escrevendo uma função utilitária que deve ter seu próprio argumento opcional para controlar a pré-alocação.

Também é importante ressaltar que você deve usar o + operador se você estiver concatenando literais de string.

Quando você concatena literais de string ou constantes de string usando o operador +, o compilador cria uma única string.Nenhuma concatenação de tempo de execução ocorre.

Como:Concatenar múltiplas strings (Guia de programação C#)

A seguir pode haver mais uma solução alternativa para concatenar várias strings.

String str1 = "sometext";
string str2 = "some other text";

string afterConcate = $"{str1}{str2}";

interpolação de strings

O mais eficiente é usar StringBuilder, assim:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@jonezy:String.Concat é bom se você tiver algumas pequenas coisas.Mas se você estiver concatenando megabytes de dados, seu programa provavelmente irá falhar.

Experimente estes 2 trechos de código e você encontrará a solução.

 static void Main(string[] args)
    {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < 10000000; i++)
        {
            s.Append( i.ToString());
        }
        Console.Write("End");
        Console.Read();
    }

Contra

static void Main(string[] args)
    {
        string s = "";
        for (int i = 0; i < 10000000; i++)
        {
            s += i.ToString();
        }
        Console.Write("End");
        Console.Read();
    }

Você descobrirá que o primeiro código terminará muito rápido e a memória estará em boa quantidade.

O segundo código talvez a memória fique boa, mas vai demorar mais...muito mais tempo.Então se você tem um aplicativo para muitos usuários e precisa de velocidade, use o 1º.Se você tiver um aplicativo para um usuário de curto prazo, talvez possa usar os dois ou o segundo será mais "natural" para os desenvolvedores.

Saúde.

System.String é imutável.Quando modificamos o valor de uma variável string, uma nova memória é alocada para o novo valor e a alocação de memória anterior é liberada.System.StringBuilder foi projetado para ter o conceito de uma string mutável onde uma variedade de operações podem ser executadas sem alocação de um local de memória separado para a string modificada.

Outra solução:

dentro do loop, use List em vez de string.

List<string> lst= new List<string>();

for(int i=0; i<100000; i++){
    ...........
    lst.Add(...);
}
return String.Join("", lst.ToArray());;

é muito rápido.

Realmente depende do seu padrão de uso.Uma referência detalhada entre string.Join, string,Concat e string.Format pode ser encontrada aqui: String.Format não é adequado para registro intensivo

(Esta é na verdade a mesma resposta que dei para esse pergunta)

Para apenas duas strings, você definitivamente não deseja usar o StringBuilder.Há algum limite acima do qual a sobrecarga do StringBuilder é menor que a sobrecarga da alocação de várias strings.

Então, para mais de 2-3 cordas, use Código de DannySmurf.Caso contrário, basta usar o operador +.

Dependeria do código.StringBuilder geralmente é mais eficiente, mas se você estiver concatenando apenas algumas strings e fazendo tudo em uma linha, as otimizações de código provavelmente cuidarão disso para você.É importante pensar também na aparência do código:para conjuntos maiores, o StringBuilder tornará mais fácil a leitura; para os pequenos, o StringBuilder apenas adicionará confusão desnecessária.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top