Inicialização de string padrão: NULL ou Empty? [fechadas]


130

Eu sempre inicializei minhas strings em NULL, pensando que NULL significa a ausência de um valor e "" ou String.Empty é um valor válido. Ultimamente, tenho visto mais exemplos de código em que String.Empty é considerado o valor padrão ou representa nenhum valor. Isso me parece estranho, com os tipos anuláveis ​​recém-adicionados em c #, parece que estamos dando passos para trás com seqüências de caracteres por não usar o NULL para representar 'No Value'.

O que você usa como inicializador padrão e por quê?

Edit: Com base nas respostas, mais meus pensamentos adicionais

  1. Evitando o tratamento de erros Se o valor não deve ser nulo, por que foi definido NULLem primeiro lugar? Talvez seja melhor identificar o erro no local em que ocorre, em vez de encobri-lo durante todo o resto da sua base de código?

  2. Evitando verificações nulas Se você está cansado de fazer verificações nulas no código, não seria melhor abstrair as verificações nulas? Talvez envolva (ou estenda!) Os métodos de string para torná-los NULLseguros? O que acontece se você usa constantemente String.Emptye um nulo funciona no seu sistema, você começa a adicionar NULLcheques de qualquer maneira?

Não posso deixar de voltar à opinião de que é preguiça. Qualquer DBA lhe daria nove maneiras de bobo se você usasse '' em vez de nullno banco de dados dele. Penso que os mesmos princípios se aplicam à programação e deve haver alguém para dar um tapa na cabeça daqueles que usam String.Emptymais do que NULLpara não representar nenhum valor.

Perguntas relacionadas


"Os sãos"? Não devo ser uma Dana, eu sei.
vfilby

@ Joel, estou impressionado com quantas pessoas não têm idéia sobre Zim ou GIR. Também estou impressionado com alguns dos meus amigos que acham repulsivo. Não estou dizendo que é pura bondade, mas há ótimas pepitas de humor por lá.
vfilby

Eu sei, mas às vezes é divertido fingir o contrário.
Dana the Sane

1
Eu corri para este problema em coleções de formulários MVC ou variáveis ​​de sessão muito, eu achei a coisa mais útil foi converter null em String.Empty com o ?? taquigrafia e, em seguida, aplique qualquer operação de cadeia necessária. por exemplo. (item ?? String.Empty) .Trim (). ToUpper ()
sonjz

4
isso não é construtivo?
Nawfal

Respostas:


111

+1 para distinguir entre "vazio" e NULL. Concordo que "vazio" deve significar "válido, mas em branco" e "NULL" devem significar "inválido".

Então, eu responderia sua pergunta assim:

vazio quando desejo um valor padrão válido que possa ou não ser alterado, por exemplo, o nome do meio de um usuário.

NULL quando houver um erro se o código a seguir não definir o valor explicitamente.


11
Distinguir entre NULL e vazio é ótimo quando há realmente uma diferença entre os dois. Porém, existem muitos casos em que não há diferença e, portanto, ter duas maneiras de representar a mesma coisa é um passivo.
Greg Smalter 5/11

6
@ Greg: Embora eu concorde que a variedade tem potencial para confusão, também pode ser um grande trunfo. A convenção simples e consistente de escrever "" ou NULL para diferenciar valores válidos e inválidos tornará seu código mais fácil de entender. É por isso que eu sempre testei booleanos com "if (var)", ponteiros com "if (var! = NULL)" e números inteiros com "if (var! = 0)" - todos significam a mesma coisa para o compilador, mas eles carregam informações adicionais que ajudam o desenvolvedor ruim que mantém meu código.
Adam Liss

32

De acordo com o MSDN :

Inicializando cadeias com o Emptyvalor em vez de null, você pode reduzir as chances de NullReferenceExceptionocorrência.

Sempre usar IsNullOrEmpty()é uma boa prática, no entanto.


45
Só porque você está reduzindo as chances da exceção não significa que a exceção não deva estar acontecendo. Se o seu código depende da existência de um valor, ele deve gerar uma exceção!
Rmeador 5/08

1
Claro, não há argumento lá. OTOH, se você está apenas juntando as cordas ... Acho que depende do estilo, da experiência e da situação da codificação.
Tomalak

Isto é principalmente o que eu uso para distinguir qual usar também.
PositiveGuy

3
Não se esqueça IsNullOrWhiteSpace () para .NET framework 4+
Coops

13

Por que você deseja que sua string seja inicializada? Você não precisa inicializar uma variável quando declara uma e, na IMO, deve fazê-lo somente quando o valor que você está atribuindo for válido no contexto do bloco de código.

Eu vejo muito isso:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else
{
  name = "bar";
}

return name;

Não inicializar para null seria tão eficaz. Além disso, na maioria das vezes você deseja que um valor seja atribuído. Ao inicializar para nulo, é possível perder os caminhos de código que não atribuem um valor. Igual a:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else if (othercondition)
{
  name = "bar";
}

return name; //returns null when condition and othercondition are false

Quando você não inicializa para nulo, o compilador gera um erro dizendo que nem todos os caminhos de código atribuem um valor. Claro, este é um exemplo muito simples ...

Matthijs


No Visual Studio, que acredito que quase todo programador de C # usa, sua segunda situação (sem a = null) geraria um aviso, exatamente pelo motivo que você declarou - não importa se o valor padrão de uma string é nulo. se você não garantir uma atribuição em todos os caminhos de código, o IDE (e / ou suponho que o compilador subjacente [?]) gerará um aviso. Apesar de advertências não impedirá a compilação, eles ainda estão lá - deixando aqueles que são facilmente resolvidos pode ajudar a outros Ofuscação que podem justificar a atenção do programador
Código Jockey

que eu saiba, a primeira situação será perfeitamente feliz sem a inicialização de nameto null(sem avisos), porque todo caminho de código atribui um valor a name- não é necessário inicializar lá
Code Jockey

8

Para a maioria dos softwares que na verdade não são software de processamento de strings, a lógica do programa não deve depender do conteúdo das variáveis ​​de strings. Sempre que vejo algo assim em um programa:

if (s == "value")

Eu tenho um mau pressentimento. Por que existe uma string literal neste método? O que está definindo s? Ele sabe que a lógica depende do valor da string? Ele sabe que precisa ser minúsculo para funcionar? Devo corrigir isso alterando-o para uso String.Compare? Devo estar criando Enume analisando?

Nessa perspectiva, chega-se a uma filosofia de código bastante simples: você evita examinar o conteúdo de uma string sempre que possível. Comparar uma string com String.Emptyé realmente apenas um caso especial de compará-la a um literal: é algo a ser evitado, a menos que você realmente precise.

Sabendo disso, não pisco quando vejo algo assim em nossa base de código:

string msg = Validate(item);
if (msg != null)
{
   DisplayErrorMessage(msg);
   return;
}

Eu sei que Validateisso nunca voltaria String.Empty, porque escrevemos um código melhor do que isso.

Claro, o resto do mundo não funciona assim. Quando o seu programa está lidando com a entrada do usuário, bancos de dados, arquivos e assim por diante, você deve considerar outras filosofias. Lá, é o trabalho do seu código impor ordem ao caos. Parte dessa ordem é saber quando uma string vazia deve significar String.Emptye quando deve significar null.

(Apenas para ter certeza de que não estava falando sério, procurei em `String.IsNullOrEmpty 'na nossa base de código. Todas as 54 ocorrências estão nos métodos que processam a entrada do usuário, retornam valores dos scripts Python, examinam os valores recuperados de APIs externas etc.)


6

Este é realmente um buraco na linguagem C #. Não há como definir uma sequência que não possa ser nula. Isso causa problemas tão simples quanto o que você está descrevendo, o que força os programadores a tomar uma decisão que eles não deveriam tomar, pois em muitos casos NULL e String.Empty significam a mesma coisa. Isso, por sua vez, pode forçar outros programadores a lidar com NULL e String.Empty, o que é irritante.

Um problema maior é que os bancos de dados permitem definir campos que são mapeados para uma string C #, mas os campos do banco de dados podem ser definidos como NOT NULL. Portanto, não há como representar com precisão, digamos, um campo varchar (100) NOT NULL no SQL Server usando um tipo C #.

Outros idiomas, como Spec #, permitem isso.

Na minha opinião, a incapacidade do C # de definir uma string que não permita nulo é tão ruim quanto a incapacidade anterior de definir um int que permita nulo.

Para responder completamente à sua pergunta: Eu sempre uso uma string vazia para a inicialização padrão, pois é mais semelhante à forma como os tipos de dados do banco de dados funcionam. (Edit: Esta declaração não era clara. Deveria ler "Eu uso uma string vazia para a inicialização padrão quando NULL é um estado supérfluo, da mesma maneira que configurei uma coluna do banco de dados como NOT NULL se NULL seria um estado supérfluo. Da mesma forma , muitas das minhas colunas do banco de dados são configuradas como NOT NULL, portanto, quando eu as incluir em uma string C #, a string estará vazia ou terá um valor, mas nunca será NULL. Em outras palavras, eu apenas inicializo uma string para NULL. se null tiver um significado distinto do significado de String.Empty, e acho que esse caso é menos que comum (mas as pessoas aqui deram exemplos legítimos deste caso). ")


O uso de String.Empty é semelhante apenas a uma das maneiras pelas quais uma string de banco de dados é definida. Usar null para representar nenhum valor é muito mais congruente com um nvarchar nulo. Eu acho que qualquer DBA que valha a pena dar-lhe um tapa de nove maneiras tolas se você usasse '' para representar nenhum valor.
vfilby

Na verdade, Greg, você entendeu errado. São os tipos de valores não anuláveis ​​que menos "como os tipos de banco de dados funcionam", porque eles nunca podem conter um nulo e, portanto, nunca podem ser mapeados para uma coluna anulável. No contrato, qualquer sequência pode mapear para qualquer coluna varchar.
Tor Haugen

Você está certo, minha última afirmação não foi clara o suficiente. Na maioria das vezes, minhas colunas do banco de dados NÃO são NULL (porque não haveria diferença entre o significado de string vazia e NULL); portanto, tento manter minhas strings semelhantes por nunca armazenar nulas nelas, e foi isso que quis dizer.
Greg Smalter 6/11/08

5

Depende.

Você precisa saber se o valor está ausente (é possível que ele não seja definido)?

A cadeia vazia é um valor válido para o uso dessa cadeia?

Se você respondeu "sim" a ambos, será melhor usar nulo. Caso contrário, você não pode dizer a diferença entre "sem valor" e "sequência vazia".

Se você não precisa saber se não há valor, a sequência vazia provavelmente é mais segura, pois permite ignorar as verificações nulas onde quer que você a use.



3

Eu o defino como "" ou nulo - sempre verifico usando String.IsNullOrEmpty, portanto, tudo bem.

Mas o nerd interior em mim diz que devo defini-lo como nulo antes de ter um valor adequado para ele ...



2

É possível que essa seja uma técnica de prevenção de erros (recomendável ou não ..)? Como "" ainda é uma sequência, você poderá chamar funções de sequência que resultariam em uma exceção se fosse NULL?


1
Essa é a desculpa que normalmente ouço, parece preguiça. "Não quero me incomodar em verificar esse valor, por isso vou usar um atalho" é como me parece.
vfilby

Sim, eu não estou discordando. Pode haver algumas situações em que reduzindo a quantidade de verificação de erros de código é bom, mas chamadas de função que não têm efeito não é o maior mal ..
Dana the Sane

2

Eu sempre os inicializo como NULL.

Eu sempre uso string.IsNullOrEmpty(someString)para verificar o seu valor.

Simples.


1

Depende da situação. Na maioria dos casos, uso String.Empty porque não quero fazer verificações nulas toda vez que tento usar uma string. Isso torna o código muito mais simples e é menos provável que você introduza falhas indesejadas de NullReferenceException.

Eu só defino a string como nula quando preciso saber se ela foi configurada ou não e onde uma string vazia é algo válido para defini-la. Na prática, acho essas situações raras.


1

Uma string vazia é um valor (um pedaço de texto que, aliás, passa a não conter letras). Nulo significa sem valor.

Inicializo variáveis ​​como nulas quando desejo indicar que elas não apontam para ou contêm valores reais - quando a intenção é sem valor.


1

Reiterando a resposta do Tomalak, lembre-se de que quando você atribui uma variável de cadeia a um valor inicial nulo, sua variável não é mais um objeto de cadeia; mesmo com qualquer objeto em c #. Portanto, se você tentar acessar quaisquer métodos ou propriedades para sua variável e estiver assumindo que é um objeto de sequência, receberá a exceção NullReferenceException.


1

Nulo deve ser usado apenas nos casos em que um valor é opcional. Se o valor não for opcional (como 'Nome' ou 'Endereço'), o valor nunca deve ser nulo. Isso se aplica a bancos de dados, POCOs e interface do usuário. Nulo significa "esse valor é opcional e está ausente no momento".

Se o seu campo não for opcional, você deve inicializá-lo como a sequência vazia. Inicializá-lo como nulo colocaria seu objeto em um estado inválido (inválido por seu próprio modelo de dados).

Pessoalmente, prefiro que as strings não sejam anuláveis ​​por padrão, mas somente anuláveis ​​se declararmos uma "string?". Embora talvez isso não seja viável ou lógico em um nível mais profundo; não tenho certeza.



0

Eu acho que não há razão para não usar nulo para um valor não atribuído (ou neste local em um fluxo de programa que não esteja ocorrendo). Se você deseja distinguir, há == nulo. Se você apenas deseja verificar um determinado valor e não se importa se é nulo ou diferente, String.Equals ("XXX", MyStringVar) funciona perfeitamente.

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.