Qual é o ponto da propriedade string.Empty


35

Por que a propriedade foi string foo = string.Emptyincluída na BCL? Parece mais detalhado e não mais claro do que apenas usar uma string vazia ( string foo = "")


6
Nitpick: não faz parte do idioma. Faz parte do BCL. O VB.NET e o F # podem usá-lo, assim como qualquer outra linguagem .NET.
Oded

19
Porque caso contrário, você não poderia fazer coisas más como typeof(string).GetField("Empty").SetValue(null, " ");;)
Mason Wheeler

11
@MasonWheeler - As alegrias da reflexão. Para o mal real, você precisa de introspecção, não é?
Oded

11
@MasonWheeler, +1. Oh Deus, os óculos, eles não fazem nada!]
Machado

11
@MasonWheeler Isso é puro mal destilado. Eu amo isto. Pergunte se você está interessado: não seria mais seguro (e com desempenho decente) ter escrito como public static string Empty { get { return string.Intern(""); } }?
Jesse C. Slicer

Respostas:


55

Só posso assumir aqui:

string.Emptyfoi definido para explicitação - ao inicializar uma sequência, pode não estar claro a partir do contexto que ""foi realmente explicitamente entendido como inicializador (em vez de, nulldigamos " "ou apenas como marcador de posição durante o teste). Usar string.Emptyé uma resposta definitiva para esse tipo de enigma.

Também pode ser um retrocesso para C - uma sequência vazia em C não é uma sequência vazia. É uma matriz de caracteres cujo primeiro caractere é nulo (portanto, vazio), que não é o mesmo que C #. O que quero dizer aqui é que, em diferentes idiomas, você representaria uma cadeia vazia de maneiras diferentes (e elas podem ter significados diferentes) - ter um string.Emptyimpedimento a essa ambiguidade.

Ao contrário do que os outros dizem sobre vários objetos - isso não é um problema, pois qualquer literal de cadeia será internada na compilação. Isso inclui o valor de string.Empty- "". Sempre que um deles é repetido no código, o objeto será recuperado do pool interno. Isso é verdade por domínio de aplicativo .


5
+1 por ser a única resposta correta até o momento.
Psr

Alguns idiomas podem nem ter uma string vazia literal. Aparentemente, Pascal padrão não.
dan04

2
"uma string vazia em C não é uma string vazia" - mas ainda assim, se você escrever "", você entenderá {'\0'}, portanto não haveria diferença entre uma literal de string vazia e outra maneira indireta de defini-la.
detly

14

Não tenho 100% de certeza das fontes onde as aprendi, mas alguns dos pontos para usá-lo incluem:

  • Cada string em um assembly .NET é única, portanto, ter

    string foo = "";
    string bar = "";
    

    resulta em 2 strings no conjunto de saída, uma vez que as strings são imutáveis. Ter as duas referências string.Emptyreduz o tamanho da montagem.

  • Explicitação. Quando você se deparar com string.Emptya intenção, fica claro que é uma string vazia. Mas se você se deparar com foo = ""o programador removeu o conteúdo da string durante o teste e esqueceu de adicioná-la novamente, ou deveria ser assim?

11
Parece um comportamento estranho manter duas seqüências idênticas na memória. Isso é de fato o que é feito?
Rig

36
De fato, o oposto é feito - é chamado de internação por string (mais precisamente, internação de literais). Eu sei com certeza que é feito em Java e Python, e tenho certeza de que também é o caso nas linguagens .NET. Obviamente, isso só pode acontecer no escopo de uma única unidade de tradução; portanto, a menos que o carregador dinâmico unifique esses dados, você poderá acabar com uma sequência vazia por arquivo de programa. Ainda não muito.

9
@delnan está absolutamente certo. ""/ string.Emptysão internados e apenas um objeto será criado.
Oded

11
@ Andy - Todos os literais de string são internados no .NET. Nem todas as cordas. As seqüências criadas programaticamente não são internadas por padrão. Consulte String.Intern no MSDN.
Oded

3
@Oded et alia: Na verdade, nenhum de vocês está exatamente certo. Primeiro, os literais são internados em uma montagem, mas não necessariamente entre as montagens . Segundo, se a cadeia de caracteres vazia é ou não internada em assemblies é um detalhe de implementação; algumas versões do CLR fazem e outras não. Há um link para o meu artigo sobre esse fato em uma das outras respostas; veja para detalhes.
Eric Lippert

2

Nenhum objeto será criado para string.Empty. O uso ""criará um objeto que provavelmente virá do pool interno de strings.

No passado, as pessoas realizavam testes e String.Emptyeram um pouco mais rápidas, mas é uma micro-otimização.

String.Empty é este:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 

2
Então o seu ponto é ...?

11
O ponto é String.Empty é basicamente uma constante para "". Encontre o autor de String.cs para um significado mais profundo. :)
Jon Raynor

0

É uma questão de otimização do consumo de memória e otimização da comparação de cadeias. Toda vez que você estiver usando uma sequência vazia no seu aplicativo, estará alocando um objeto de sequência contendo 0 caracteres. Quanto à comparação de strings, isso pode ser feito comparando referências (ponteiros) em vez de caractere por caractere, o que é mais rápido, mesmo para as strings vazias.

Se você estiver usando muitas vezes a mesma string em seu aplicativo, poderá usar o mesmo tipo de mecanismo chamando String.Intern () com sua string. Mas se você estiver usando cada sequência apenas uma vez, usará apenas mais memória.

Portanto, o String.Empty é apenas uma otimização de caso especial que vale a pena fazer para a maioria dos aplicativos .Net, por isso foi integrada ao BCL.

Para mais detalhes sobre este assunto, recomendo fortemente a leitura do post de Eric Lippert no blog .

Você também deve dar uma olhada nesta documentação referenciada por seu post no blog.


4
As respostas somente do link não são boas respostas. Se Eric alguma vez reorganizar seu blog, essa resposta se tornará inútil. Por favor resumir o post aqui por isso temos toda a informação para a mão.
ChrisF

7
@ ChrisF: Eu nunca consigo reorganizar o blog. Isso seria uma mudança radical, e você sabe como me sinto sobre isso.
Eric Lippert

11
@EricLippert - eu sei que você nunca faria isso, no entanto, as respostas apenas do link não são boas e precisamos incentivar as pessoas a perceber isso.
ChrisF

3
@EricLippert Não se trata apenas de links efêmeros. Também se trata de educação para os leitores aqui, deve haver pelo menos conteúdo suficiente diretamente na resposta para que os leitores possam formar uma opinião sobre se devem seguir o link. E a resposta deve fazer sentido, mesmo em uma cópia offline do SE.
Gilles 'SO- stop be evil'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.