Pergunta

O que é mais eficiente para o compilador e a prática recomendada para verificar se uma string está em branco?

  1. Verificando se o comprimento da string == 0
  2. Verificando se a string está vazia (strVar == "")

Além disso, a resposta depende do idioma?

Foi útil?

Solução

Sim, depende do idioma, pois o armazenamento de strings difere entre os idiomas.

  • Strings do tipo Pascal: Length = 0.
  • Sequências de estilo C: [0] == 0.
  • .LÍQUIDO: .IsNullOrEmpty.

Etc.

Outras dicas

Em linguagens que usam strings de estilo C (terminadas em nulo), comparando com "" será mais rápido.Essa é uma operação O(1), enquanto o comprimento de uma string no estilo C é O(n).

Em linguagens que armazenam comprimento como parte do objeto string (C#, Java, ...) a verificação do comprimento também é O(1).Nesse caso, verificar diretamente o comprimento é mais rápido, pois evita a sobrecarga de construção da nova string vazia.

Na rede:

string.IsNullOrEmpty( nystr );

strings podem ser nulas, então .Length às vezes lança uma NullReferenceException

Em linguagens que usam strings no estilo C (terminadas em nulo), comparar com "" será mais rápido

Na verdade, talvez seja melhor verificar se o primeiro caractere da string é '\0':

char *mystring;
/* do something with the string */
if ((mystring != NULL) && (mystring[0] == '\0')) {
    /* the string is empty */
}

Em Perl há uma terceira opção: a string é indefinida.Isso é um pouco diferente de um ponteiro NULL em C, apenas porque você não recebe uma falha de segmentação ao acessar uma string indefinida.

Em Java 1.6, a classe String possui um novo método está vazia

Há também a biblioteca comum de Jacarta, que tem o está em branco método.Em branco é definido como uma string que contém apenas espaços em branco.

Supondo que sua pergunta seja .NET:

Se você deseja validar sua string contra nulidade também use IsNullOrEmpty, se você já sabe que sua string não é nula, por exemplo ao verificar TextBox.Text etc., não use IsNullOrEmpty, e aí entra sua pergunta.
Então, na minha opinião, String.Length tem menos desempenho do que comparação de strings.

Eu testei (também testei com C#, mesmo resultado):

Module Module1
  Sub Main()
    Dim myString = ""


    Dim a, b, c, d As Long

    Console.WriteLine("Way 1...")

    a = Now.Ticks
    For index = 0 To 10000000
      Dim isEmpty = myString = ""
    Next
    b = Now.Ticks

    Console.WriteLine("Way 2...")

    c = Now.Ticks
    For index = 0 To 10000000
      Dim isEmpty = myString.Length = 0
    Next
    d = Now.Ticks

    Dim way1 = b - a, way2 = d - c

    Console.WriteLine("way 1 took {0} ticks", way1)
    Console.WriteLine("way 2 took {0} ticks", way2)
    Console.WriteLine("way 1 took {0} ticks more than way 2", way1 - way2)
    Console.Read()
  End Sub
End Module

Resultado:

Way 1...
Way 2...
way 1 took 624001 ticks
way 2 took 468001 ticks
way 1 took 156000 ticks more than way 2

O que significa que a comparação exige muito mais do que a verificação do comprimento da string.

String.IsNullOrEmpty() funciona apenas em .net 2.0 e superior, para .net 1/1.1, costumo usar:

if (inputString == null || inputString == String.Empty)
{
    // String is null or empty, do something clever here. Or just expload.
}

Eu uso String.Empty em oposição a "" porque "" criará um objeto, enquanto String.Empty não criará - eu sei que é algo pequeno e trivial, mas ainda prefiro não criar objetos quando não preciso deles!(Fonte)

Na verdade, na IMO, a melhor maneira de determinar é o método IsNullOrEmpty() da classe string.

http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.

Atualizar:Presumi que .Net, em outras línguas, isso poderia ser diferente.

Nesse caso, verificar diretamente o comprimento é mais rápido, pois evita a sobrecarga de construção da nova string vazia.

@DerekPark:Isso não e sempre verdade."" é uma string literal, portanto, em Java, quase certamente já estará internada.

Para cordas C,

if (s[0] == 0)

será mais rápido do que qualquer um

if (strlen(s) == 0)

ou

if (strcmp(s, "") == 0)

porque você evitará a sobrecarga de uma chamada de função.

@Nathan

Na verdade, talvez seja melhor verificar se o primeiro caractere da string é '\0':

Quase mencionei isso, mas acabei deixando de lado, já que liguei strcmp() com a string vazia e verificando diretamente o primeiro caractere da string são O (1).Basicamente, você paga apenas por uma chamada de função extra, o que é bem barato.Se você realmente precisa da melhor velocidade absoluta, porém, definitivamente faça uma comparação direta do primeiro caractere com 0.

Sinceramente, eu sempre uso strlen() == 0, porque eu tenho nunca escrevi um programa em que esse era realmente um problema de desempenho mensurável e acho que essa é a maneira mais legível de expressar a verificação.

Novamente, sem conhecer o idioma, é impossível saber.

Porém, recomendo que você escolha a técnica que faz mais sentido para o programador de manutenção que segue e terá que dar continuidade ao seu trabalho.

Eu recomendo escrever uma função que faça explicitamente o que você deseja, como

#define IS_EMPTY(s) ((s)[0]==0)

ou comparável.Agora não há dúvida de que você está verificando.

Depois de ler este tópico, conduzi um pequeno experimento, que rendeu duas descobertas distintas e interessantes.

Considere o seguinte.

strInstallString    "1" string

O texto acima é copiado da janela local do depurador do Visual Studio.O mesmo valor é usado em todos os três exemplos a seguir.

if ( strInstallString == "" ) === if ( strInstallString == string.Empty )

A seguir está o código exibido na janela de desmontagem do depurador do Visual Studio 2013 para esses dois casos fundamentalmente idênticos.

if ( strInstallString == "" )
003126FB  mov         edx,dword ptr ds:[31B2184h]
00312701  mov         ecx,dword ptr [ebp-50h]
00312704  call        59DEC0B0            ; On return, EAX = 0x00000000.
00312709  mov         dword ptr [ebp-9Ch],eax
0031270F  cmp         dword ptr [ebp-9Ch],0
00312716  sete        al
00312719  movzx       eax,al
0031271C  mov         dword ptr [ebp-64h],eax
0031271F  cmp         dword ptr [ebp-64h],0
00312723  jne         00312750

if ( strInstallString == string.Empty )
00452443  mov         edx,dword ptr ds:[3282184h]
00452449  mov         ecx,dword ptr [ebp-50h]
0045244C  call        59DEC0B0        ; On return, EAX = 0x00000000.
00452451  mov         dword ptr [ebp-9Ch],eax
00452457  cmp         dword ptr [ebp-9Ch],0
0045245E  sete        al
00452461  movzx       eax,al
00452464  mov         dword ptr [ebp-64h],eax
00452467  cmp         dword ptr [ebp-64h],0
0045246B  jne         00452498

if ( strInstallString == string.Empty ) não é significativamente diferente

if ( strInstallString.Length == 0 )
003E284B  mov         ecx,dword ptr [ebp-50h]
003E284E  cmp         dword ptr [ecx],ecx
003E2850  call        5ACBC87E        ; On return, EAX = 0x00000001.
003E2855  mov         dword ptr [ebp-9Ch],eax
003E285B  cmp         dword ptr [ebp-9Ch],0
003E2862  setne       al
003E2865  movzx       eax,al
003E2868  mov         dword ptr [ebp-64h],eax
003E286B  cmp         dword ptr [ebp-64h],0
003E286F  jne         003E289C

A partir das listagens de código de máquina acima, geradas pelo módulo NGEN do .NET Framework, versão 4.5, tiro as seguintes conclusões.

  1. O teste de igualdade em relação à string literal vazia e à propriedade estática string.Empty na classe System.string são, para todos os efeitos práticos, idênticos.A única diferença entre os dois trechos de código é a origem da primeira instrução de movimento, e ambos são deslocamentos relativos a ds, o que implica que ambos se referem a constantes incorporadas.

  2. Testar a igualdade em relação à string vazia, como uma propriedade literal ou string.Empty, configura uma chamada de função de dois argumentos, que indica desigualdade retornando zero.Baseio essa conclusão em outros testes que realizei há alguns meses, nos quais segui alguns de meus próprios códigos na divisão gerenciado/não gerenciado e vice-versa.Em todos os casos, qualquer chamada que exija dois ou mais argumentos coloca o primeiro argumento no registro ECX e o segundo no registro EDX.Não me lembro como os argumentos subsequentes foram passados.No entanto, a configuração da chamada parecia mais com __fastcall do que com __stdcall.Da mesma forma, os valores de retorno esperados sempre apareciam no registro EAX, o que é quase universal.

  3. Testar o comprimento da string configura uma chamada de função de um argumento, que retorna 1 (no registro EAX), que é o comprimento da string que está sendo testada.

  4. Dado que o código de máquina imediatamente visível é quase idêntico, a única razão que posso imaginar seria responsável pelo melhor desempenho da igualdade da string ao longo do comprimento da picada relatado por Brilhante é que a função de dois argumentos que realiza a comparação é significativamente melhor otimizada do que a função de um argumento que lê o comprimento da instância da string.

Conclusão

Por uma questão de princípio, evito comparar com a string vazia como um literal, porque o literal da string vazia pode parecer ambíguo no código-fonte.Para esse fim, minhas classes auxiliares do .NET definiram há muito tempo a string vazia como uma constante.Embora eu use string.Vazio para comparações diretas e in-line, a constante ganha seu valor para definir outras constantes cujo valor é a string vazia, porque uma constante não pode ser atribuída string.Vazio como seu valor.

Este exercício resolve, de uma vez por todas, qualquer preocupação que eu possa ter sobre o custo, se houver, de comparar com qualquer um dos string.Vazio ou a constante definida pelas minhas classes auxiliares.

No entanto, também levanta uma questão intrigante para substituí-lo;por que está comparando com string.Vazio mais eficiente do que testar o comprimento da string?Ou o teste usado pelo Shinny é invalidado pela forma como o loop é implementado?(Acho isso difícil de acreditar, mas, novamente, já fui enganado antes, e tenho certeza que você também!)

Há muito que assumi que sistema.string os objetos eram strings contadas, fundamentalmente semelhantes à String Básica (BSTR) há muito estabelecida que conhecemos há muito tempo no COM.

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