Pergunta

Em .NET, o que é a diferença entre String.Empty e "", e eles são intercambiáveis, ou há alguma referência subjacente ou questões de localização em torno de igualdade que String.Empty irá garantir não são um problema?

Foi útil?

Solução

antes da versão 2.0 NET, "" cria um objecto enquanto string.Empty cria nenhum objecto ref , o que torna string.Empty mais eficiente.

Na versão 2.0 e posterior do .NET, todas as ocorrências de "" se referem ao mesmo literal de cadeia, o que significa "" é equivalente a .Empty, mas ainda não tão rápido quanto .Length == 0.

.Length == 0 é a opção mais rápida, mas .Empty faz para um código mais limpo ligeiramente.

Veja a .NET especificação para mais informações .

Outras dicas

O que é a diferença entre String.Empty e "", e são eles interchangable

string.Empty é um campo só de leitura enquanto "" é uma constante de tempo de compilação. Lugares onde eles se comportam de forma diferente são:

Padrão O valor do parâmetro em C # 4.0 ou superior

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
    //... implementation
}

expressão CASE na instrução switch

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}

argumentos Atributo

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type

As respostas anteriores foram correto para .NET 1.1 (veja a data da postagem eles ligados: 2003). Como de NET 2,0 e mais tarde, não existe essencialmente qualquer diferença. O JIT vai acabar referenciando o mesmo objeto na pilha de qualquer maneira.

De acordo com a especificação C #, secção 2.4.4.5: http://msdn.microsoft.com/en-us/ biblioteca / aa691090 (VS.71) .aspx

Cada literal de cadeia não resulta necessariamente em uma nova instância string. Quando duas ou mais strings literais que são equivalentes de acordo com o operador de corda de igualdade (Seção 7.9.7) aparecem no mesmo conjunto, estas strings literais se referem à mesma instância string.

Alguém sequer menciona isso nos comentários de Brad Abram pós

Em resumo, o resultado prático "" vs. String.Empty é nulo. O JIT irá descobrir isso no final.

Eu descobri, pessoalmente, que o JIT é a maneira mais inteligente do que eu e então eu tento não ficar muito inteligente com otimizações micro-compilador assim. O JIT vai se desdobrar para loops (), remova código redundante, métodos de inline, etc melhor e, por vezes, mais apropriado do que eu ou o compilador C # jamais poderia antecipar antes da mão. Deixe o JIT fazer o seu trabalho:)

String.Empty é uma somente leitura campo enquanto "" é uma const . Isto significa que você não pode usar String.Empty em uma instrução switch, porque não é uma constante.

Outra diferença é que String.Empty gera maior código CIL. Enquanto o código para fazer referência a "" e String.Empty é o mesmo comprimento, o compilador não otimizar concatenação (ver Eric Lippert blog ) para argumentos string.Empty. As seguintes funções equivalentes

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}

gerar esse IL

.method private hidebysig instance string foo() cil managed
{
    .maxstack 8
    L_0000: ldstr "foo"
    L_0005: ret 
}
.method private hidebysig instance string bar() cil managed
{
    .maxstack 8
    L_0000: ldstr "bar"
    L_0005: ldsfld string [mscorlib]System.String::Empty
    L_000a: call string [mscorlib]System.String::Concat(string, string)
    L_000f: ret 
}

As respostas acima são tecnicamente correto, mas o que você pode realmente quer usar, para melhor legibilidade do código e menos chance de uma exceção é String.IsNullOrEmpty (s)

I tendem a usar String.Empty em vez de "" por um simples, mas não a razão óbvia: "" e "" não são os mesmos, o primeiro, na verdade, tem 16 caracteres de zero largura nele. desenvolvedor, obviamente, nenhuma competente vai colocar e zero caracteres de largura em seu código, mas se eles chegar lá, ele pode ser um pesadelo de manutenção.

Notas:

Use String.Empty em vez de "".

Este é mais de velocidade do que o uso de memória, mas é uma dica útil. o "" é um literal, irá atuar como um literal: no primeiro uso é criado e para as seguintes utilizações sua referência é retornado. Apenas um instância de "" serão armazenados na memória, não importa quantas vezes nós use-o! Eu não vejo quaisquer penalidades de memória aqui. O problema é que cada vez que o "", é utilizado um circuito de comparação é executada para verificar se o "" já está na piscina interna. Por outro lado, String.Empty é uma referência a uma "" armazenado na zona de memória .NET Framework . String.Empty está apontando para o mesmo endereço de memória para VB.NET e C # formulários. Então, por que procurar uma referência cada vez que precisar "" quando você tem essa referência em String.Empty?

Referência: String.Empty vs ""

String.Empty não cria um objeto enquanto "" faz. A diferença, como apontado aqui , é trivial, no entanto.

Todas as instâncias de "" são os mesmos, literal de cadeia internado (ou deveriam ser). Então, você realmente não vai estar jogando um novo objeto na pilha cada vez que você usar "", mas apenas criar uma referência para o mesmo objeto, internado. Dito isto, eu prefiro string.Empty. Eu acho que torna o código mais legível.

string mystring = "";
ldstr ""

ldstr empurra um novo objeto referência a um literal cadeia armazenada nos metadados.

string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty

ldsfld empurra o valor de um campo estático para a avaliação pilha

I tendem a usar String.Empty vez de "" porque IMHO é mais clara e menos VB-ish.

Vindo para isso de um ponto de Entity Framework de vista: versões EF 6.1.3 parece tratar String.Empty e "" de forma diferente ao validar.

string.Empty é tratado como um valor nulo para fins de validação e lançará um erro de validação se for usado em um campo obrigatório (atribuído); onde como "" vai passar na validação e não jogue o erro.

Este problema pode ser resolvido em EF 7+. Referência: - https://github.com/aspnet/EntityFramework/issues/2610 ).

Edit:. [Obrigatório (AllowEmptyStrings = true)] vai resolver esse problema, permitindo string.Empty para validar

Desde String.Empty não é uma constante de tempo de compilação que você não pode usá-lo como um valor padrão na definição da função.

public void test(int i=0,string s="")
    {
      // Function Body
    }

Eric Lippert escreveu (17 de junho de 2013):
"o primeiro algoritmo que eu já trabalhei no compilador C # foi o otimizador que concatenations cordas alças Infelizmente eu não conseguem. port essas otimizações para o Roslyn codebase antes de eu sair;! espero que alguém vai chegar a esse "

Aqui estão alguns Roslyn x64 resultados a partir de janeiro de 2019. Apesar das declarações de consenso das outras respostas nesta página, não me parece que o JIT x64 atual está tratando todos estes casos identicamente, quando tudo estiver dito e feito.

Nota, em particular, no entanto, que apenas um desses exemplos realmente acaba chamando String.Concat, e eu estou supondo que isso é por motivos de correção obscuros (em oposição a um descuido optimization). As outras diferenças parecem mais difícil de explicar.


padrão (String) + {default (String), "", String.Empty}

static String s00() => default(String) + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s01() => default(String) + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s02() => default(String) + String.Empty;
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

"" + {default (String), "", String.Empty}

static String s03() => "" + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s04() => "" + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    add  rsp,28h
    ret

static String s05() => "" + String.Empty;
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

String.Empty + {default (String), "", String.Empty}

static String s06() => String.Empty + default(String);
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

static String s07() => String.Empty + "";
    mov  rax,[String::Empty]
    mov  rax,qword ptr [rax]
    mov  rdx,rax
    test rdx,rdx
    jne  _L
    mov  rdx,rax
_L: mov  rax,rdx
    add  rsp,28h
    ret

static String s08() => String.Empty + String.Empty;
    mov  rcx,[String::Empty]
    mov  rcx,qword ptr [rcx]
    mov  qword ptr [rsp+20h],rcx
    mov  rcx,qword ptr [rsp+20h]
    mov  rdx,qword ptr [rsp+20h]
    call F330CF60                 ; <-- String.Concat
    nop
    add  rsp,28h
    ret


Detalhes do teste

Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false

Quando você está analisando visualmente através de código, "" aparece colorizado o caminho cordas são a cores. string.Empty parece com uma classe-membro de acesso regular. Durante um olhar rápido, é mais fácil de detectar "" ou intuir o significado.

Spot the cordas (stack overflow colorização não é exatamente ajudar, mas em VS isso é mais óbvio):

var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;

Todos aqui deu alguns bons clarificação teórica. Eu tinha uma dúvida similar. Então, eu tentei codificação de um básicas sobre ele. E eu achei a diferença. Aqui está a diferença.

string str=null;
Console.WriteLine(str.Length);  // Exception(NullRefernceException) for pointing to null reference. 


string str = string.Empty;
Console.WriteLine(str.Length);  // 0

Assim, parece meio "nulo" absolutamente vazios e significa "string.Empty" Ele contém algum tipo de valor, mas está vazia.

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