Novembro 16, 2009

Concatenando Strings

Posted in .NET Framework às 14:17 por Henrry Pires

string1 & string2 & string3 & … string100 = Comprar hardware mais potente.

É uma prática muito comum concatenar várias string, por exemplo dentro dum ciclo, mas sendo uma prática comum não propriamente quer dizer que a melhor forma de atingir o objectivo, porque?

Vou fazer uma aplicação muito pequena para demonstrar o ‘porquê’ da questão.

Module Module1

    Sub Main()

        Dim resultado As String = String.Empty

        For i = 0 To 100
            resultado &= i.ToString()
        Next

    End Sub

End Module

Esta console application, muito simples, o único que vai fazer é, concatenar 100 vezes a variável ‘resultado’ com com o ToString da variável ‘i’.

Após compilado para release, se formos ver o IL gerado, recorrendo para tal ao ildasm.exe, (que vem instalado com a .NET Framework SDK) vamos obter o seguinte resultado:

.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       32 (0x20)
  .maxstack  2
  .locals init ([0] string resultado,
           [1] int32 i)
  IL_0000:  ldsfld     string [mscorlib]System.String::Empty
  IL_0005:  stloc.0
  IL_0006:  ldc.i4.0
  IL_0007:  stloc.1
  IL_0008:  ldloc.0
  IL_0009:  ldloca.s   i
  IL_000b:  call       instance string [mscorlib]System.Int32::ToString()
  IL_0010:  call       string [mscorlib]System.String::Concat(string, string)
  IL_0015:  stloc.0
  IL_0016:  ldloc.1
  IL_0017:  ldc.i4.1
  IL_0018:  add.ovf
  IL_0019:  stloc.1
  IL_001a:  ldloc.1
  IL_001b:  ldc.i4.s   100
  IL_001d:  ble.s      IL_0008
  IL_001f:  ret
} // end of method Module1::Main

Vou somente abordar a linha que está sublinhada, visto não ser o propósito deste post analisar, o IL gerado na sua totalidade.

Na linha sublinhada está a ser invocado o método Shared ‘Concat’ da classe string. Vamos agora recorrer ao .Net Reflector para ver o código executado neste método

Public Shared Function Concat(ByVal str0 As String, _
                              ByVal str1 As String) As String
    If String.IsNullOrEmpty(str0) Then
        If String.IsNullOrEmpty(str1) Then
            Return String.Empty
        End If
        Return str1
    End If
    If String.IsNullOrEmpty(str1) Then
        Return str0
    End If
    Dim length As Integer = str0.Length
    Dim dest As String = String.FastAllocateString((length + str1.Length))
    String.FillStringChecked(dest, 0, str0)
    String.FillStringChecked(dest, length, str1)
    Return dest
End Function

Pelo código que o Reflector nos devolve, podemos ver que está ser retornada no fim da função a variável ‘dest’, que mais não é do que uma nova instância da classe string, contendo as duas strings que lhe foram passadas por parâmetro, ‘str0′ e ‘str1’

Portanto, por cada concatenação de duas strings, é gerada uma terceira string. Se por exemplo, incluirmos isto dentro de um ciclo, vamos ter uma enorme quantidade de instâncias da classe string.

Como então evitar este problema?
Vou refazer o exemplo acima, de modo optimizar a concatenação das strings.

Module Module1

    Sub Main()

        Dim resultado As new System.Text.StringBuilder()

        For i = 0 To 100
            resultado.Append(i.ToString())
        Next

    End Sub

End Module

A classe StringBuilder é excelente para esta finalidade, pois independentemente do número de vezes que o método Append(…) for invocado,  vai criar uma única string (recorrendo ao .Net Reflector poderá ser constatado), e para obtermos a o resultado final, basta-nos invocar o método ToString(), exemplo: resultado.ToString().

Conclusão

Sempre que tivermos mais do que quatro concatenações para fazer vale a pena usar a classe StringBuilder, pois vai-nos poupar instâncias “desnecessárias” da classe string.

Anúncios

1 Comentário »

  1. triathlon said,

    I simply could not depart your website before suggesting that I actually loved the standard information an individual supply to your visitors?

    Is going to be again continuously to check up on
    new posts


Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: