2011-02-06 15 views
7

Uso di 'modello' variabile locale non assegnato. È il messaggio di errore che sto ricevendo È proprio dove dico se (modello == null). Non sono sicuro del motivo per cui mi sta dando un errore in fase di compilazione ... qualcuno per favore aiuto."Uso della variabile locale non assegnata" in un metodo generico

public static T TryGet<T>(string fileName) where T : new() 
{ 
    T model; 
    using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication()) 
    { 
     using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storageFile)) 
     { 
      if (stream.Length > 0) 
      { 
       var serializer = new DataContractSerializer(typeof(T)); 
       model = (T)serializer.ReadObject(stream); 
      } 
     } 
    } 
    if (model == null) 
    { 
     model = new T(); 
    } 
    return model; 
} 

risposta

15

Come indica l'errore, non è possibile utilizzare una variabile locale finché il compilatore non può dimostrare che è stato assegnato un valore.

Nel tuo caso, se la tua condizione if è falsa, la variabile model non viene mai assegnata.

È possibile risolvere il problema assegnando un primo valore prima:

T model = default(T); 

Nota che se T è un tipo struct, model == null può mai essere vero.

Si dovrebbe modificare il codice per

using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication()) 
using (var stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storageFile)) 
{ 
    if (stream.Length > 0) 
    { 
     var serializer = new DataContractSerializer(typeof(T)); 
     return (T)serializer.ReadObject(stream); 
    } 
    else 
    { 
     return new T(); 
    } 
} 
+0

Risposta buona, descrittiva. Oh, e congratulazioni :-) –

1

Perché model è una variabile locale, il compilatore è che si dà che l'errore, perché viene assegnato solo nel if. Se la condizione dell'istruzione if non è vera, model non verrà assegnato un valore. Prova a dargli un valore predefinito di null oppure aggiungi un'altra istruzione e assegna model al suo interno.

T model = null; 

Le variabili locali non vengono inizializzate automaticamente, ma le variabili di istanza sono.

public class MyClass<T> 
{ 
    private T instanceVariable; // automatically initialized 

    public void MyMethod() 
    { 
     T localVariable; // not automatically initialized 
    } 
} 
3

Il compilatore non sa cosa assegnare fino a quando gli si dice.

Invece di utilizzare T model;T model = default(T);

Per maggiori informazioni: http://msdn.microsoft.com/en-us/library/xwth0h0d(v=vs.80).aspx

edit: un'altra opzione è quella di spostare solo la nuova dichiarazione di blocco prima della deserializzazione. In questo modo, avrai un nuovo oggetto o l'oggetto deserializzato proprio come ora.

+1

Questo non ha nulla a che fare con l'essere un tipo di riferimento. Inoltre, 'T' non è un tipo di riferimento. – SLaks

+0

@SLaks, non vedo nulla nel post che suggerisca che 'T' non sia un tipo di riferimento. Il codice così com'è funzionerà solo per un tipo di valore. Per i tipi di riferimento, dovrà assegnare null, default o un nuovo oggetto. –

+0

A meno che non scriviate 'dove T: class',' T' non è un tipo di riferimento. – SLaks

3

Quando si lavora con le variabili locali, devono sempre essere assegnato un valore prima di essere letta.

Il motivo è perché di solito, quando lo sviluppatore omette l'inizializzazione, si affida al runtime per assegnargli il valore predefinito, ma nel caso lo abbia dimenticato, ciò può causare alcuni bug non necessari.

Nel caso di lavorare con i generici, e non specificando se vi aspettate una ReferenceType o un ValueType, non si può semplicemente inizializzarlo assegnando null. In questo caso è necessario utilizzare lo default keyword.

Inizializza la variabile su null per i tipi di riferimento o assegna 0 per i tipi di valori numerici. Per le strutture, inizializzerà ogni membro al suo valore predefinito.

Nell'esempio che è stato pubblicato, il confronto con null mi consente di supporre che questo metodo possa essere utilizzato solo con ReferenceTypes, in tal caso, è preferibile aggiungere anche il vincolo class.

+0

Penso che nel CLR non ci possa essere un valore ben definito * fino a * set (e il compilatore C# prende semplicemente la strada di far fare al programmatore invece di spingere in un 'predefinito (T) "da qualche parte) - Credo che vedere un post SO recentemente ha detto che la variabile" slot "* è accessibile * tramite qualche bytecode diretto. –

Problemi correlati