Inizializzazione stringa predefinita: NULL o Vuota? [chiuso]


130

Ho sempre inizializzato le mie stringhe su NULL, pensando che NULL significhi l'assenza di un valore e "" o String.Empty sia un valore valido. Ultimamente ho visto più esempi di codice in cui String.Empty è considerato il valore predefinito o non rappresenta alcun valore. Questo mi sembra strano, con i nuovi tipi di nullable aggiunti in c # sembra che stiamo facendo passi indietro con le stringhe non usando NULL per rappresentare 'No Value'.

Cosa usi come inizializzatore predefinito e perché?

Modifica: in base alle risposte, ulteriori miei ulteriori pensieri

  1. Evitare la gestione degli errori Se il valore non deve essere nullo, perché è stato impostato NULLin primo luogo? Forse sarebbe meglio identificare l'errore nel luogo in cui si verifica piuttosto che coprirlo per tutto il resto della tua base di codice?

  2. Evitare controlli null Se sei stanco di fare controlli null nel codice, non sarebbe meglio astrarre i controlli null? Forse avvolgi (o estendi!) I metodi stringa per renderli NULLsicuri? Cosa succede se si utilizza costantemente String.Emptye accade che un null funzioni correttamente nel sistema, si inizia NULLcomunque ad aggiungere controlli?

Non posso fare a meno di tornare all'opinione che è pigrizia. Qualsiasi DBA ti darebbe uno schiaffo in nove modi se facessi "" invece che nullnel suo database. Penso che gli stessi principi si applichino alla programmazione e dovrebbe esserci qualcuno che colpisca coloro che si muovono al di String.Emptysopra della testa che usano piuttosto che NULLrappresentare alcun valore.

domande correlate


'The Sane'? Non devo essere una Dana, lo so.
vfilby,

@Joel, sono stupito da quante persone non hanno idea di Zim o GIR, sono anche sorpreso da alcuni dei miei amici che lo trovano ripugnante. Non dire che è pura bontà, ma ci sono fantastiche pepite di umorismo lì dentro.
vfilby,

Lo so, ma a volte è divertente fingere diversamente.
Dana the Sane,

1
Ho riscontrato questo problema sulle raccolte di moduli MVC o sulle variabili di sessione, ho scoperto che la cosa più utile era convertire null in String.Empty con ?? scorciatoia e quindi applicare qualsiasi operazione stringa richiesta. per esempio. (item ?? String.Empty) .Trim (). ToUpper ()
sonjz

4
questo non è costruttivo ??
nawfal,

Risposte:


111

+1 per la distinzione tra "vuoto" e NULL. Sono d'accordo che "vuoto" dovrebbe significare "valido, ma vuoto" e "NULL" dovrebbe significare "non valido".

Quindi risponderei alla tua domanda in questo modo:

vuoto quando desidero un valore predefinito valido che può essere modificato o meno, ad esempio il secondo nome di un utente.

NULL quando si tratta di un errore se il codice che segue non imposta esplicitamente il valore.


11
Distinguere tra NULL e vuoto è grande quando in realtà c'è una differenza tra i due. Ci sono molti casi, tuttavia, in cui non c'è differenza, e quindi avere due modi di rappresentare la stessa cosa è una responsabilità.
Greg Smalter,

6
@Greg: Anche se sono d'accordo sul fatto che la varietà abbia il potenziale di confusione, può anche essere una grande risorsa. La semplice e coerente convenzione di scrivere "" o NULL per distinguere tra valori validi e non validi renderà più facile la comprensione del codice. Questo è il motivo per cui provo sempre booleani con "if (var)," puntatori con "if (var! = NULL)" e numeri interi con "if (var! = 0)" - significano tutti la stessa cosa per il compilatore, ma contengono informazioni aggiuntive che aiutano il povero sviluppatore che mantiene il mio codice.
Adam Liss,

32

Secondo MSDN :

Inizializzando le stringhe con il Emptyvalore anziché null, è possibile ridurre le possibilità che si NullReferenceExceptionverifichi.

L'uso sempre IsNullOrEmpty()è comunque una buona pratica.


45
Solo perché stai riducendo le possibilità dell'eccezione non significa che l'eccezione non dovrebbe accadere. Se il tuo codice dipende da un valore presente, dovrebbe generare un'eccezione!
rmeador,

1
Certo, nessuna discussione lì. OTOH, se stai solo aggiungendo delle stringhe insieme ... Penso che dipenda dallo stile di codifica, dall'esperienza e dalla situazione.
Tomalak,

Questo è principalmente ciò che uso distinguere quale utilizzare anche.
Positivo

3
Non dimenticare IsNullOrWhiteSpace () per .NET framework 4+
Coops

13

Perché vuoi che la tua stringa venga inizializzata? Non devi inizializzare una variabile quando ne dichiari una e IMO, dovresti farlo solo quando il valore che stai assegnando è valido nel contesto del blocco di codice.

Lo vedo molto:

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

return name;

Non inizializzare su null sarebbe altrettanto efficace. Inoltre, molto spesso si desidera assegnare un valore. Inizializzando su null, è possibile perdere potenzialmente percorsi di codice che non assegnano un valore. Così:

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 non si inizializza su null, il compilatore genererà un errore che dice che non tutti i percorsi di codice assegnano un valore. Certo, questo è un esempio molto semplice ...

Matthijs


In Visual Studio, che credo quasi tutti i programmatori di C # utilizzano, la tua seconda situazione (senza il = null) genererebbe un avviso, esattamente per il motivo che hai indicato - non importa se il valore predefinito di una stringa è null. se non garantisci un'assegnazione attraverso ogni percorso di codice, l'IDE (e / o suppongo che il compilatore sottostante [?]) genererà un avviso. Sebbene gli avvisi non impediscano la compilazione, sono ancora lì - lasciare quelli che sono facilmente risolti può aiutare a offuscare gli altri che potrebbero meritare l'attenzione del programmatore
Code Jockey

a mia conoscenza, la prima situazione sarà perfettamente felice senza inizializzazione di namea null(nessun avviso), perché ogni percorso di codice assegna un valore name- non c'è bisogno di inizializzare lì a tutti
Codice Jockey

8

Per la maggior parte dei software che non sono in realtà software di elaborazione di stringhe, la logica del programma non dovrebbe dipendere dal contenuto delle variabili di stringa. Ogni volta che vedo qualcosa di simile in un programma:

if (s == "value")

Ho una brutta sensazione. Perché c'è una stringa letterale in questo metodo? Che cos'è l'impostazione s? Sa che la logica dipende dal valore della stringa? Sa che deve essere minuscola per funzionare? Dovrei risolvere questo problema modificandolo per l'uso String.Compare? Dovrei creare Enume analizzare in esso?

Da questo punto di vista, si arriva a una filosofia del codice piuttosto semplice: si evita di esaminare i contenuti di una stringa laddove possibile. Il confronto di una stringa con String.Emptyè davvero solo un caso speciale di confronto con un valore letterale: è qualcosa da evitare a meno che non sia necessario.

Sapendo questo, non lampeggio quando vedo qualcosa di simile nella nostra base di codice:

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

So che Validatenon tornerà mai più String.Empty, perché scriviamo un codice migliore di quello.

Certo, il resto del mondo non funziona così. Quando il tuo programma ha a che fare con input dell'utente, database, file e così via, devi tenere conto di altre filosofie. Ecco, è compito del tuo codice imporre l'ordine nel caos. Parte di quell'ordine è sapere quando una stringa vuota dovrebbe significare String.Emptye quando dovrebbe significare null.

(Solo per essere sicuro di non parlare dal mio culo, ho appena cercato nella nostra base di codice "String.IsNullOrEmpty". Tutte e 54 le occorrenze sono in metodi che elaborano l'input dell'utente, restituiscono valori dagli script Python, esaminano i valori recuperati da API esterne, ecc.)


6

Questo è in realtà un buco nel linguaggio C #. Non è possibile definire una stringa che non può essere nulla. Ciò causa problemi semplici come quello che stai descrivendo, che costringe i programmatori a prendere una decisione che non dovrebbero prendere, poiché in molti casi NULL e String.Empty significano la stessa cosa. Ciò, a sua volta, può in seguito costringere altri programmatori a gestire sia NULL che String.Empty, il che è fastidioso.

Un problema maggiore è che i database consentono di definire i campi associati a una stringa C #, ma i campi del database possono essere definiti come NOT NULL. Pertanto, non è possibile rappresentare in modo accurato, ad esempio, un campo varchar (100) NOT NULL in SQL Server utilizzando un tipo C #.

Altre lingue, come Spec #, lo consentono.

A mio avviso, l'incapacità di C # di definire una stringa che non consente null è altrettanto grave della precedente incapacità di definire un int che consente null.

Per rispondere completamente alla tua domanda: utilizzo sempre una stringa vuota per l'inizializzazione predefinita perché è più simile a come funzionano i tipi di dati del database. (Modifica: questa affermazione era molto poco chiara. Dovrebbe leggere "Uso una stringa vuota per l'inizializzazione predefinita quando NULL è uno stato superfluo, più o meno allo stesso modo ho impostato una colonna di database come NOT NULL se NULL sarebbe uno stato superfluo. Allo stesso modo , molte delle mie colonne DB sono impostate come NOT NULL, quindi quando le inserisco in una stringa C #, la stringa sarà vuota o avrà un valore, ma non sarà mai NULL. In altre parole, inizializzo solo una stringa su NULL se null ha un significato che è distinto dal significato di String.Empty e trovo che il caso sia meno del comune (ma le persone qui hanno fornito esempi legittimi di questo caso). ")


L'uso di String.Empty è simile solo a uno dei modi in cui è definita una stringa del database. L'uso di null per rappresentare alcun valore è molto più congruente con un nvarchar null. Penso che qualsiasi DBA degno del loro sale ti darebbe uno schiaffo in nove modi se non usassi "" per rappresentare alcun valore.
Vfilby,

A dire il vero, Greg, hai sbagliato. Sono i tipi di valore non annullabili che meno "funzionano i tipi di database" perché non possono mai contenere un valore null e quindi non possono mai essere associati a una colonna nullable. Nel contratto, qualsiasi stringa può essere mappata su qualsiasi colonna varchar.
Tor Haugen,

Hai ragione, la mia ultima affermazione non era abbastanza chiara. La maggior parte delle volte, le colonne del mio database NON SONO NULL (perché non ci sarebbe alcuna differenza tra il significato di stringa vuota e NULL), quindi cerco di mantenere simili le mie stringhe non memorizzando mai nulla in esse, e questo è ciò che intendevo.
Greg Smalter,

5

Dipende.

Devi essere in grado di dire se il valore è mancante (è possibile che non sia definito)?

La stringa vuota è un valore valido per l'utilizzo di quella stringa?

Se hai risposto "sì" ad entrambi, allora vorrai usare null. Altrimenti non puoi distinguere tra "nessun valore" e "stringa vuota".

Se non hai bisogno di sapere se non c'è alcun valore, la stringa vuota è probabilmente più sicura, in quanto ti consente di saltare i controlli null ovunque tu lo usi.



3

L'ho impostato su "" o null - controllo sempre utilizzando String.IsNullOrEmpty, quindi va bene lo stesso.

Ma il geek interiore in me dice che dovrei impostarlo su null prima di avere un valore adeguato per esso ...



2

È possibile che si tratti di una tecnica di prevenzione degli errori (consigliabile o no ..)? Dato che "" è ancora una stringa, saresti in grado di chiamare funzioni stringa che genererebbero un'eccezione se fosse NULL?


1
Questa è la scusa che sento normalmente, sembra solo pigrizia. "Non voglio preoccuparmi di controllare questo valore, quindi ho intenzione di prendere una scorciatoia" è come mi sembra.
vfilby,

Sì, non sono in disaccordo. Potrebbero esserci alcune situazioni in cui ridurre la quantità di codice di controllo degli errori è utile, ma le chiamate di funzione che non hanno alcun effetto non sono le migliori ..
Dana the Sane,

2

Li ho sempre inizializzati come NULL.

Ho sempre usato string.IsNullOrEmpty(someString)per controllare il suo valore.

Semplice.


1

Dipende dalla situazione. Nella maggior parte dei casi uso String.Empty perché non voglio fare controlli null ogni volta che provo ad usare una stringa. Rende il codice molto più semplice e hai meno probabilità di introdurre arresti anomali NullReferenceException indesiderati.

Ho impostato la stringa su null solo quando ho bisogno di sapere se è stata impostata o meno e dove una stringa vuota è qualcosa di valido su cui impostarla. In pratica, trovo queste situazioni rare.


1

Una stringa vuota è un valore (un pezzo di testo che, per inciso, sembra non contenere alcuna lettera). Null significa nessun valore.

Inizializzo le variabili su null quando desidero indicare che non indicano o contengono valori effettivi, quando l'intento è per nessun valore.


1

Ribadendo la risposta di Tomalak, tieni presente che quando assegni una variabile stringa a un valore iniziale di null, la tua variabile non è più un oggetto stringa; lo stesso con qualsiasi oggetto in C #. Pertanto, se si tenta di accedere a metodi o proprietà per la variabile e si presuppone che sia un oggetto stringa, si otterrà l'eccezione NullReferenceException.


1

Null deve essere utilizzato solo nei casi in cui un valore è facoltativo. Se il valore non è facoltativo (come "Nome" o "Indirizzo"), il valore non dovrebbe mai essere nullo. Questo vale per i database, i POCO e l'interfaccia utente. Null significa "questo valore è facoltativo ed è attualmente assente".

Se il campo non è facoltativo, è necessario inizializzarlo come stringa vuota. Inizializzarlo come null porrebbe l'oggetto in uno stato non valido (non valido dal proprio modello dati).

Personalmente preferirei che le stringhe non fossero nullable per impostazione predefinita, ma invece nullable se dichiarassimo una "stringa?". Anche se forse questo non è fattibile o logico a un livello più profondo; non sono sicuro.


0

Le stringhe non sono tipi di valore e non lo saranno mai ;-)


0

Penso che non vi sia motivo di non utilizzare null per un valore non assegnato (o in questo punto in un flusso di programma non presente). Se vuoi distinguere, c'è == null. Se vuoi solo verificare un determinato valore e non ti importa se è nullo o qualcosa di diverso, String.Equals ("XXX", MyStringVar) va bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.