Qual é a diferença entre String.Empty e “” (string vazia)?
-
02-07-2019 - |
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?
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.
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:
-
Eu costumava U + FEFF neste exemplo.
-
Não tenho certeza se SO vai comer esses personagens, mas tente você mesmo com um dos muitos personagens de largura zero
-
Eu só veio sobre este graças a https://codegolf.stackexchange.com/
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 emString.Empty
?
Referência: String.Empty
vs ""
String.Empty não cria um objeto enquanto "" faz. A diferença, como apontado aqui , é trivial, no entanto.
Ele só não importa!
Alguns discussão passado deste:
http://www.codinghorror.com/blog/archives/000185.html
http://blogs.msdn.com/brada/ Arquivo / 2003/04/22 / 49997.aspx
http://blogs.msdn.com/brada/ Arquivo / 2003/04/27 / 50014.aspx
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.