Respostas:
No .NET anterior à versão 2.0, ""
cria um objeto enquanto string.Empty
não cria ref de objeto , o que tornastring.Empty
mais eficiente.
Na versão 2.0 e posterior do .NET, todas as ocorrências de ""
referem-se à mesma string literal, o que significa que ""
é equivalente a .Empty
, mas ainda não tão rápido quanto.Length == 0
.
.Length == 0
é a opção mais rápida, mas .Empty
para um código um pouco mais limpo.
Consulte a especificação do .NET para obter mais informações .
string.IsNullOrEmpty( stringVar )
.
qual é a diferença entre String.Empty e "" e eles são intercambiáveis
string.Empty
é um campo somente leitura, enquanto ""
é uma constante de tempo de compilação. Os locais onde eles se comportam de maneira diferente são:
Valor padrão 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 de caso na instrução switch
string str = "";
switch(str)
{
case string.Empty: // Error: A constant value is expected.
break;
case "":
break;
}
Argumentos de atributo
[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type
String.Empty
como argumento na maioria dos casos. Você está certo que todos os exemplos mostram isso you simply can't put a (run-time) "value" into (compile-time) metadata
e é isso que os exemplos pretendem mostrar.
As respostas anteriores estavam corretas para o .NET 1.1 (veja a data da postagem que eles vincularam: 2003). A partir do .NET 2.0 e posterior, não há essencialmente nenhuma diferença. O JIT acabará referenciando o mesmo objeto no heap de qualquer maneira.
De acordo com a especificação C #, seção 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx
Cada literal de cadeia não resulta necessariamente em uma nova instância de cadeia. Quando dois ou mais literais de sequência equivalentes de acordo com o operador de igualdade de sequência (Seção 7.9.7) aparecem no mesmo assembly, esses literais de sequência se referem à mesma instância de sequência.
Alguém até menciona isso nos comentários do post de Brad Abram
Em resumo, o resultado prático de "" vs. String.Empty é nulo. O JIT descobrirá isso no final.
Descobri, pessoalmente, que o JIT é muito mais inteligente do que eu e, por isso, tento não ficar muito esperto com otimizações de micro-compiladores como essa. O JIT se desdobra para loops (), remove código redundante, métodos em linha, etc. melhor e em momentos mais apropriados do que eu ou o compilador C # jamais poderia antecipar antes. Deixe o JIT fazer seu trabalho :)
String.Empty
é um campo somente leitura enquanto ""
é uma const . Isso significa que você não pode usar String.Empty
em uma instrução switch porque não é uma constante.
default
palavra-chave que pode promover a leitura, sem, impedir a modificação acidental, e tem uma constante de tempo de compilação, embora para ser honesto, eu ainda acho String.Empty é mais legível do que padrão, mas mais lento para digitar
Outra diferença é que String.Empty gera um código CIL maior. Embora o código para referenciar "" e String.Empty tenha o mesmo comprimento, o compilador não otimiza a concatenação de strings (consulte a publicação no blog de Eric Lippert ) para obter os argumentos String.Empty. As seguintes funções equivalentes
string foo()
{
return "foo" + "";
}
string bar()
{
return "bar" + string.Empty;
}
gerar essa 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
}
"bar " + (ok ? "" : "error")
As respostas acima são tecnicamente corretas, mas o que você realmente deseja usar, para melhor legibilidade do código e menor chance de exceção, é String.IsNullOrEmpty (s)
--foo=$BAR
, provavelmente deseja identificar a diferença entre eles esquecerem de definir uma var env e eles não passarem o sinalizador. string.IsNullOrEmpty
geralmente é um cheiro de código que você não validou suas entradas corretamente ou está fazendo coisas estranhas. Geralmente, você não deve aceitar cadeias de caracteres vazias quando realmente deseja usar null
, ou algo como o tipo Talvez / Opção.
Costumo usar String.Empty
mais do que ""
por um motivo simples, mas não óbvio:
""
e ""
NÃO é o mesmo, o primeiro tem 16 caracteres de largura zero. Obviamente, nenhum desenvolvedor competente colocará zero caracteres de largura em seu código, mas se eles chegarem lá, pode ser um pesadelo de manutenção.
Notas:
Eu usei U + FEFF neste exemplo.
Não tenho certeza se o SO vai comer esses caracteres, mas tente você mesmo com um dos muitos caracteres de largura zero
Só me deparei com isso graças a https://codegolf.stackexchange.com/
Use em String.Empty
vez de ""
.
Isso é mais por velocidade do que por uso de memória, mas é uma dica útil. Como
""
é um literal, ele atuará como um literal: no primeiro uso, ele é criado e, para os seguintes usos, sua referência é retornada. Apenas uma instância de""
será armazenada na memória, não importa quantas vezes a utilizemos! Não vejo nenhuma penalidade de memória aqui. O problema é que, sempre que""
é usado, um loop de comparação é executado para verificar se o""
já está no pool interno. Por outro lado,String.Empty
é uma referência a um""
arquivo armazenado na zona de memória do .NET Framework .String.Empty
está apontando para o mesmo endereço de memória para aplicativos VB.NET e C #. Então, por que procurar uma referência sempre que precisar ?""
quando tiver essa referência emString.Empty
Referência: String.Empty
vs""
String.Empty não cria um objeto, enquanto "" cria. A diferença, como apontado aqui , é trivial, no entanto.
Todas as instâncias de "" são iguais, literal de cadeia interna (ou deveriam ser). Então você realmente não estará lançando um novo objeto na pilha toda vez que usar "", mas apenas criando uma referência ao mesmo objeto interno. Dito isto, eu prefiro string.Empty. Eu acho que torna o código mais legível.
Isso não importa!
Algumas discussões anteriores sobre isso:
http://www.codinghorror.com/blog/archives/000185.html
string mystring = "";
ldstr ""
ldstr
envia uma nova referência de objeto a um literal de seqüência de caracteres armazenado nos metadados.
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
coloca o valor de um campo estático na pilha de avaliação
Eu tendem a usar em String.Empty
vez de ""
porque IMHO é mais claro e menos VB-ish.
Eric Lippert escreveu (17 de junho de 2013):
"O primeiro algoritmo em que trabalhei no compilador C # foi o otimizador que lida com concatenações de cadeias. Infelizmente, não consegui portar essas otimizações para a base de código de Roslyn antes de sair; espero que alguém chegar a isso! "
Aqui estão alguns resultados do Roslyn x64 a partir de janeiro de 2019. Apesar das observações consensuais das outras respostas nesta página, não me parece que o JIT x64 atual esteja tratando todos esses casos de forma idêntica, quando tudo estiver dito e feito.
Observe, em particular, que apenas um desses exemplos acaba chamando String.Concat
, e acho que isso é por motivos obscuros de correção (em oposição a uma supervisão de otimização). As outras diferenças parecem mais difíceis de explicar.
default (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
"" + {padrão (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 + {padrão (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
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
Chegando a isso do ponto de vista do Entity Framework: o EF versões 6.1.3 parece tratar String.Empty e "" de maneira 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 "" passará na validação e não lançará o erro.
Esse problema pode ser resolvido no EF 7+. Referência: - https://github.com/aspnet/EntityFramework/issues/2610 ).
Edit: [Required (AllowEmptyStrings = true)] resolverá esse problema, permitindo que string.Empty seja validada.
Como String.Empty não é uma constante em tempo de compilação, você não pode usá-lo como um valor padrão na definição de função.
public void test(int i=0,string s="")
{
// Function Body
}
public void test(int i=0, string s=string.Empty) {}
não irá compilar e dizer "valor do parâmetro padrão para 's' deve ser uma constante em tempo de compilação obras resposta do OP..
Quando você digitaliza visualmente o código, "" aparece colorido da maneira que as strings são coloridas. string.Empty se parece com um acesso de membro de classe regular. Durante uma rápida olhada, é mais fácil identificar "" ou intuir o significado.
Identifique as strings (a colorização do estouro de pilha não ajuda exatamente, mas no 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;
\u00ad
.
Todo mundo aqui deu um bom esclarecimento teórico. Eu tinha uma dúvida semelhante. Então, eu tentei uma codificação básica nele. 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
Parece que "Nulo" significa absolutamente nulo e "String.Empty" significa que contém algum tipo de valor, mas está vazio.
""
versus string.Empty
. Somente ao tentar dizer se a string está vazia, null
foi mencionado.
string.Empty
e qual foi a lógica por trás de declará-la como emreadonly
vez deconst
.