2012-09-13 7 views
11

Voglio verificare se una variabile è inizializzata in fase di esecuzione, a livello di programmazione. Per rendere meno misteriose le ragioni, vedere il seguente codice incompleto:C# - verifica dell'inizializzazione di una variabile

string s; 

if (someCondition) s = someValue; 
if (someOtherCondition) s = someOtherValue; 

bool sIsUninitialized = /* assign value correctly */; 

if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s."); 

E completare il bit pertinente.

Una soluzione hacky è di inizializzare s con un valore di default:

string s = "zanzibar"; 

E poi verificare se è cambiato:

bool sIsUninitialized = s == "zanzibar"; 

Tuttavia, quello che se someValue o someOtherValue capita di essere "Zanzibar" anche? Allora ho un bug. Qualche modo migliore?

+5

'string.IsNullOrEmpty (s)' – Shmiddty

+7

Questo in realtà non verrà nemmeno compilato. Le variabili devono essere inizializzate. Basta inizializzarlo su null o string.Empty. – McGarnagle

+0

Cosa succede se la variabile è inizializzata da un altro thread? Sei a tuo agio con l'impostazione del controller di memoria per generare un'eccezione all'accesso in scrittura? – HABO

risposta

12

Il codice non viene nemmeno compilato se il compilatore sa che una variabile non è stata inizializzata.

string s; 
if (condition) s = "test"; 
// compiler error here: use of unassigned local variable 's' 
if (s == null) Console.Writeline("uninitialized"); 

In altri casi è possibile utilizzare la parola chiave default se una variabile non sia stato inizializzato. Ad esempio, nel seguente caso:

class X 
{ 
    private string s; 
    public void Y() 
    { 
     Console.WriteLine(s == default(string)); // this evaluates to true 
    } 
} 

Le documentation stati che predefinito (T) darà null per tipi di riferimento, e 0 per tipi di valori. Quindi, come sottolineato nei commenti, questo è proprio lo stesso che controllare null.


Tutto questo oscura il fatto che si dovrebbe davvero inizializzare le variabili, a null o qualsiasi altra cosa, al momento del primo dichiarati.

+4

Non è 's == default (string)' un modo elegante per dire 's == null'? – dasblinkenlight

+1

@dasblinkenlight beh sì, in fondo, ma penso che renda l'intento un po 'più esplicito. – McGarnagle

+10

@dbaseman, non sono d'accordo. Oscura la ben nota comprensione di cosa sia "null". –

2

È possibile mantenere una bandiera separato che indica che la stringa è stato inizializzato:

string s = null; 
bool init = false; 
if (conditionOne) { 
    s = someValueOne; 
    init = true; 
} 
if (conditionTwo) { 
    s = someValueTwo; 
    init = true; 
} 
if (!init) { 
    ... 
} 

Questo si prenderà cura di situazioni in cui è assegnato s, inclusi i casi in cui è assegnato null, stringa vuota, o "zanzibar".

Un'altra soluzione consiste nel creare una stringa statica per indicare il valore "non inizializzato" e utilizzare Object.ReferenceEquals anziché == per verificare se è stata modificata. Tuttavia, l'approccio variabile bool esprime il tuo intento in modo molto più esplicito.

+0

Perché introdurre il flag e non solo confrontare 's' contro' null'? –

+5

@KirkWoll Questa è una grande domanda, anche se ho provato a rispondere nella risposta: perché 'SomeValueOne' o' someValueTwo' potrebbero essere legittimamente 'null'. (Aggiornamento: a quanto pare, l'OP non interessa :) – dasblinkenlight

+0

Abbastanza corretto, non ho letto abbastanza bene la tua risposta. ;) –

0

prendo valori di inizializzazione che non possono essere utilizzati, valori tipici includono String.Empty, null, -1, e un generatore stringa casuale di 256 caratteri.

+2

'string.Empty' =' "" ''. Non c'è bisogno di usare un'alternativa prolissa tre volte più. Dopo tutto, non usiamo cose come 'Int32.Zero'. –

+0

Preferisco String.Empty perché non può essere confuso con '' ''. È più facile da leggere per me. –

+2

Non dovresti essere confuso da "" "'. Veramente. È parte integrante di qualsiasi linguaggio di programmazione. –

3

Basta assegnare null per impostazione predefinita, non è un valore stringa

+0

cosa succede se 'null' è un valore valido per quella stringa da assegnare in una delle istruzioni' if'? – Servy

+0

@Servy Quindi definire una costante che rappresenta il valore non-null, non inizializzato, ad es. 'const string UninitializedString =" zanzibar ";' –

+1

@PeterGluck Quindi quel valore costante ora diventa "non valido" e, peggio, renderebbe il debug straordinariamente difficile perché se fosse successo qualche metodo per restituirlo determinando il motivo per cui sembrava non funzionare affatto causerebbe ogni sorta di mal di testa. – Servy

8

Con C# 2.0, avete l'operatore Nullable che permette di impostare un valore iniziale di null per i tipi di valore fino ad ora, permettendo cose come:

int? x = null; 

if (x.HasValue) 
{ 
    Console.WriteLine("Value for x: " + num.Value); 
} 

Quali rese: "Valore x: Null".

+2

Questo non è applicabile alle stringhe, perché è già un tipo di riferimento. – dasblinkenlight

+0

La frase introduttiva dell'OP indica "Voglio verificare se una variabile è inizializzata in fase di esecuzione". Il tipo era una stringa solo in quello che l'OP indicava era il suo "codice incompleto" usato per un esempio. –

+2

Non utilizzare valori letterali booleani negli assegni, scrivi 'if (x.HasValue)'. I letterali booleani sono significativi solo nelle inizializzazioni (o quando vengono passati come parametri) - da nessun'altra parte. –

3

Ecco un modo:

string s; 
if (someCondition) { s = someValue; } 
else if (someOtherCondition) { s = someOtherValue; } 
else { throw new Exception("Please initialize s."); } 

Console.WriteLine(s) 

Questo potrebbe essere preferibile per verificare se la stringa è nulla, perché forse someValue è un metodo che a volte può restituire null. In altre parole, forse null è un valore legittimo per inizializzare la stringa su.

Personalmente mi piace questo meglio di un flag isInitialized. Perché introdurre una variabile di flag extra a meno che non sia necessario? Non penso sia più leggibile.

+0

Ovviamente 'someValue' non è un metodo o sarebbe' SomeValue() ', ma intendo" nel caso reale (non semplificato) ". Potrebbe comunque essere "nullo" in ogni caso. –

-1

In generale, assegnare il valore predefinito a null o String.Empty. Per le situazioni in cui non è possibile utilizzare questi valori "vuoti", definire una costante per rappresentare il vostro valore non inizializzato specifico dell'applicazione:

const string UninitializedString = "zanzibar"; 

quindi fare riferimento a tale valore ogni volta che si desidera inizializzare o il test per l'inizializzazione:

string foo = UnininitializedString; 
if (foo == UninitiaizedString) { 
    // Do something 
} 

Ricorda che le stringhe sono costanti immutabili in C#, quindi c'è solo una istanza di UninitializedString (che è il motivo per cui il confronto funziona).

+1

Questa è una ricetta per il disastro. Ad un certo punto potresti finire con un legittimo compito a quel valore "non inizializzato", causando ogni sorta di confusione per i programmatori che devono cercare di determinare il motivo per cui non funziona. – Servy

+0

@Servy Non è così. Questo è esattamente il motivo per cui usi una costante denominata invece di cospargere una stringa "nuda" in tutto il codice. La costante può essere modificata secondo necessità lungo la strada. E nota che ho detto che la tua prima scelta è usare 'null' o' String.Empty'. Infatti, 'const string UninitializedString = String.Empty;' sarebbe la mia prima scelta. –

+1

In primo luogo non si cosparge mai una stringa "nuda" in tutto il codice. Si utilizza una soluzione come [questa] (http://stackoverflow.com/a/12414058/1159478) che non utilizza mai alcun valore per rappresentare un "valore non inizializzato". Il fatto che tu possa cambiarlo (in fase di compilazione) non attenua significativamente i pericoli qui. Se la stringa può essere basata sull'input dell'utente, non hai idea in fase di compilazione di ciò che l'utente potrebbe scegliere; qualunque cosa tu scelga potrebbe essere sbagliato. In realtà non è raro avere un assegnamento valido a 'null' o una stringa vuota, quindi l'utilizzo di questo non aiuta. – Servy

Problemi correlati