Impossibile utilizzare String.Empty come valore predefinito per un parametro facoltativo


89

Sto leggendo Effective C # di Bill Wagner. Nell'elemento 14 - Riduci al minimo la logica di inizializzazione duplicata , mostra il seguente esempio di utilizzo della nuova funzionalità di parametri opzionali in un costruttore:

public MyClass(int initialCount = 0, string name = "")

Si noti che ha usato ""invece di string.Empty.
Lui commenta:

Noterai [in un esempio sopra] che il secondo costruttore ha specificato "" per il valore predefinito sul parametro name , invece del più consueto string.Empty. Questo perché string.Emptynon è una costante del tempo di compilazione. È una proprietà statica definita nella classe string. Poiché non è una costante di compilazione, non è possibile utilizzarla come valore predefinito per un parametro.

Se non possiamo usare la string.Emptystatica in tutte le situazioni, allora non ne sconfigge lo scopo? Ho pensato che lo avremmo usato per essere sicuri di avere un mezzo indipendente dal sistema per fare riferimento alla stringa vuota. La mia comprensione è sbagliata? Grazie.

AGGIORNAMENTO
Solo un commento di follow-up. Secondo MSDN:

Ogni parametro facoltativo ha un valore predefinito come parte della sua definizione. Se non viene inviato alcun argomento per quel parametro, viene utilizzato il valore predefinito. I valori predefiniti devono essere costanti.

Quindi non saremo in grado di utilizzare System.Environment.NewLinenessuno dei due o utilizzare oggetti appena istanziati come valori predefiniti. Non ho ancora usato VS2010 e questo è deludente!


2
Non sono a conoscenza di differenze tra il modo in cui le stringhe vuote vengono rappresentate su piattaforme diverse. Non è come una nuova riga.
Tom Cabanski

Giusto, lo stavo pensando, quindi è solo che sembra più carino nel codice?
Mikeyg36

1
Il CLR e non il 'System' è il fattore determinante per stabilire se "" è una stringa vuota o meno. Quindi penso che si possa tranquillamente presumere che "" sia un modo indipendente dal sistema per fare riferimento a una stringa su un'implementazione CLR conforme.
Chris Taylor

"indipendente dal sistema"? ehm, al contrario di ""? (???)
Qwertie

Secondo MSDN: il valore di questo campo è la stringa di lunghezza zero, "". quindi ovviamente non ha nulla a che fare con l'indipendenza dalla piattaforma, come fanno notare molte persone. Eppure sembra ancora che le persone non sappiano davvero perché dovrebbe essere usato!
Mikeyg36

Risposte:


65

A partire dal compilatore C # 2.0, non ha comunque molto senso String.Empty, e in effetti in molti casi è una pessimizzazione, poiché il compilatore può inline alcuni riferimenti ""ma non può fare lo stesso conString.Empty .

In C # 1.1 era utile evitare di creare molti oggetti indipendenti che contenevano tutti la stringa vuota, ma quei giorni sono passati. ""funziona bene.


7
Anche in .NET 1.1 non creerebbe "molti" oggetti indipendenti. Non riesco a ricordare i dettagli delle differenze tra 1.1 e 2.0 a questo riguardo, ma non è che l'internamento letterale di stringhe sia stato introdotto solo nella 2.0.
Jon Skeet

Grazie per il chiarimento. Ho dato un'occhiata in giro e non ho trovato un buon riepilogo delle modifiche in C # 2.0, anche se sono sicuro di averne letto uno in precedenza. Ho trovato una risposta StackOverflow del 2008 con alcuni collegamenti a informazioni più tecniche. stackoverflow.com/questions/151472/…
Andy Mortimer,

1
Faccio un cenno del capo, anche se non mi piace dire che non ha molto senso stringere. Vuoto perché lo uso piuttosto pesantemente. Trovo che sia semplicemente più pulito, anche se questa è la mia opinione personale. Ci sono molti punti stringa. Vuoto non può essere utilizzato e non ho problemi a utilizzare "" in questi casi
xximjasonxx

14
Ho scoperto che è molto più facile identificare rapidamente una stringa vuota con String.Empty che guardare due volte "" per assicurarmi che non contenga un apostrofo o qualcosa di simile nascosto al suo interno. +1 per la spiegazione però.
NotMe

11
+1 Chris. Anche in VS, non puoi davvero fare una ricerca sugli usi di "" (oltre a fare lo standard Find che riporterà anche ogni corrispondenza di testo, inclusi commenti e markup). Puoi fare una ricerca su usi specifici del codice con string.Empty.
MutantNinjaCodeMonkey

53

Non c'è niente che ti impedisca di definire la tua costante per la stringa vuota se vuoi davvero usarla come valore di parametro opzionale:

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[Per inciso, una delle ragioni per preferire String.Emptysopra "", in generale, che non è stato menzionato nelle altre risposte, è che ci sono vari caratteri Unicode (falegnami zero larghezza, etc.) che sono effettivamente invisibili ad occhio nudo. Quindi qualcosa che assomiglia ""non è necessariamente una stringa vuota, mentre con String.Emptyte sai esattamente cosa stai usando. Riconosco che questa non è una fonte comune di bug, ma è possibile.]


2
Ci sono anche caratteri identificativi invisibili, quindi qualcosa che assomiglia a String_Empty non è necessariamente. Lo standard Unicode ha un capitolo ampiamente ignorato sulle considerazioni sulla sicurezza.
Jim Balter

25

Dalla domanda originale:

Ho pensato che lo avremmo usato per essere sicuri di avere un mezzo indipendente dal sistema per fare riferimento alla stringa vuota.

In che modo la stringa vuota può variare da sistema a sistema? È sempre una stringa senza caratteri! Sarei davvero paura se mai trovato un'implementazione dove string.Empty == ""restituito falso :) Questo è non è la stessa come qualcosa di simile Environment.NewLine.

Dal post di taglie di Counter Terrorist:

Voglio che String.Empty possa essere usato come parametro predefinito nella prossima versione di C #. : D

Beh, di certo non succederà.

Anche se personalmente avrei gradito anche un meccanismo di default molto diverso, il modo in cui funzionano i parametri opzionali è stato in .NET sin dall'inizio - e significa sempre incorporare una costante nei metadati, in modo che il codice chiamante possa copiare quella costante nella chiamata sito se non viene fornito alcun argomento corrispondente.

Con string.Emptyè davvero inutile: l'uso ""farà quello che vuoi; è che doloroso da usare letterale stringa? (Uso il letterale ovunque - non lo uso mai string.Empty- ma questo è un argomento diverso.)

Questo è ciò che mi sorprende di questa domanda: il reclamo ruota attorno a qualcosa che in realtà non causa un vero problema. È più importante nei casi in cui si desidera che il valore predefinito venga calcolato al momento dell'esecuzione perché potrebbe effettivamente variare. Ad esempio, potrei immaginare casi in cui vuoi essere in grado di chiamare un metodo con un DateTimeparametro e impostarlo come predefinito "l'ora corrente". Al momento, l'unica soluzione vagamente elegante che conosco è:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

... ma non è sempre appropriato.

In conclusione:

  • Dubito fortemente che questo farà mai parte di C #
  • Per string.Empty è comunque inutile
  • Per altri valori che in realtà non hanno sempre lo stesso valore, può davvero essere un dolore

Questo è effettivamente un buon modo per risolvere il problema. La stessa cosa può essere usata per trasportare / impostare altre variabili dipendenti dal dispositivo come Environment.Newline... L'unica cosa che manca dal tuo esempio sarebbe un controllo sulla variabile per null e restituire un'eccezione allo sviluppatore dicendogli che mentre è annullabile, è non accettato. if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}o qualcosa di simile. Ma questo mi piace davvero! Qualche altro avvertimento per farlo a modo tuo?
MaxOvrdrv

@ MaxOvrdrv: Non vuoi che sia nullo per essere un errore - il punto è che quando è nullo, calcoli un valore predefinito. L'avvertenza è che non consente il passaggio di null come valore valido in sé.
Jon Skeet

Hai completamente ragione su questo. Colpa mia. - E sì, sarebbe l'unico vero avvertimento, non sarebbe ... non è poi così male. Di nuovo: mi piace molto questa soluzione! :) Grazie per averlo postato! :)
MaxOvrdrv

7

Non uso mai stringhe vuote, non ne vedo il punto. Forse rende più facile per le persone che sono veramente nuove alla programmazione, ma dubito che sia utile anche per questo.


2
Forse previene la confusione ""e " ", ma non posso dire che " "sia così comune.
Greg

8
Suggerirei che chiunque non sia in grado di distinguere tra questi ha bisogno di occhiali migliori o di abbassare la risoluzione del proprio schermo. Ho una cattiva vista e non ricordo di aver mai commesso quell'errore (e devo lavorare con un sacco di codice che contiene entrambi).
Hans Olsson

2
string.Empty è utile per scoprire l'esatta intenzione del programmatore. "" non dice nulla sull'intenzione, e se l'intenzione del programmatore fosse di inizializzare la variabile in questo modo "lol" ma si è dimenticata ... in questo caso ci sono infinite possibilità e stringhe, Empty torna utile e fa un lavoro migliore
utileBee

4

Penso che l'idea alla base di string.Empty è che migliora la leggibilità. Non è come newline dove c'è qualche differenza tra il modo in cui viene rappresentato su piattaforme diverse. È un peccato che non possa essere utilizzato in un parametro predefinito. Tuttavia, non causerà alcun problema se esegui il port tra Windows e qualcosa come Mono su Linux.


5
Penso che probabilmente hai ragione sul fatto che il punto è che alcune persone considerano String.Emptypiù leggibile. . . personalmente, però, penso che sia un po 'folle. ""è probabilmente la stringa più comune che ci sia e tutti l'hanno vista un miliardo di volte, quindi come è illeggibile? String.Emptyè utile quanto se ci fosse un file Int32.Zero.
Tim Goodman

3

Per tua informazione, sembra che lo stesso vincolo sia imposto sui valori passati ai costruttori di attributi: devono essere costanti. Poiché string.empty è definito come:

public static readonly string Empty

piuttosto che una costante effettiva, non può essere utilizzata.


1

Io uso string.Empty esclusivamente per la leggibilità.

Se qualcun altro ha bisogno di leggere / modificare il mio codice in un secondo momento, sa che intendevo verificare o impostare qualcosa su una stringa vuota. L'utilizzo di just a ""volte può causare bug e confusione perché potrei aver appena dimenticato di mettere la stringa che volevo lì.

Per esempio:

if(someString == string.Empty)
{

}

vs

if(someString == "")
{

}

La prima ifaffermazione mi sembra molto più deliberata e leggibile. Poiché questa è solo una preferenza, però, non vedo davvero il successo del treno nel dover usare al ""posto di string.Empty.


-2

Forse la migliore soluzione a questo problema è un sovraccarico di questo metodo, in questo modo:

public static void PrintString() 
{ 
    PrintString(string.Empty);
}

3
Come è la risposta alla domanda precedente?
Pranav Singh,

1
Come aiuta con i valori predefiniti per i parametri opzionali?
impostazioni locali predefinite
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.