2011-02-06 15 views
7

Użycie nieprzypisanej zmiennej lokalnej "model". Czy jest to komunikat o błędzie, który otrzymuję. Jego prawo, gdzie mówię, jeśli (model == null). Nie jestem pewien, dlaczego daje mi to błąd czasu kompilacji .. ktoś proszę o pomoc."Używanie nieprzypisanej zmiennej lokalnej" w metodzie ogólnej

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; 
} 

Odpowiedz

15

Jak podaje błąd, nie można używać zmiennej lokalnej, dopóki kompilator nie może udowodnić, że została przypisana jej wartość.

W twoim przypadku, jeśli twój warunek if jest fałszywy, zmienna model nigdy nie jest przypisana.

Można rozwiązać ten problem poprzez przypisanie jej początkowej wartościową pierwszy:

T model = default(T); 

pamiętać, że jeśli T jest typu struct, model == null nigdy nie może być prawda.

powinien zmienić swój kod do

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

Dobra, opisowa odpowiedź. Aha i gratulacje :-) –

1

model Ponieważ jest to zmienna lokalna, kompilator daje Ci ten błąd ponieważ jest przypisany tylko w razie stwierdzenia. Jeśli warunek instrukcji if nie jest spełniony, model nie zostanie przypisana żadna wartość. Spróbuj podać domyślną wartość null lub dodaj instrukcję else i przypisz do niej model.

T model = null; 

Zmienne lokalne nie są inicjowane automatycznie, ale zmienne instancji są.

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

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

Kompilator nie wie, co przypisać, dopóki tego nie powie.

Zamiast T model; używać T model = default(T);

Aby uzyskać więcej informacji: http://msdn.microsoft.com/en-us/library/xwth0h0d(v=vs.80).aspx

edit: Inną opcją jest po prostu przenieść do nowego oświadczenia przed blokiem deserializacji. W ten sposób będziesz miał nowy obiekt lub deserializowany obiekt, tak jak teraz.

+1

Nie ma to nic wspólnego z byciem typem odniesienia. Poza tym 'T' nie jest typem referencyjnym. – SLaks

+0

@SLaks, Nic nie widzę w poście sugerując, że 'T' nie jest typem referencyjnym. Kod taki jak teraz działa tylko dla typu wartości. W przypadku typów odniesienia będzie musiał przydzielić wartość null, wartość domyślną lub nowy obiekt. –

+0

Jeśli nie napiszesz 'where T: class',' T' nie jest typem odniesienia. – SLaks

3

Podczas pracy ze zmiennymi lokalnymi, muszą zawsze być przypisana wartość przed dostępne.

Powodem tego jest to, że zazwyczaj, gdy programista pomija inicjalizację, polega na środowisku wykonawczym, aby przypisać mu wartość domyślną, ale w przypadku, gdyby zapomniał, może to spowodować niepotrzebne błędy.

W przypadku pracy z leków generycznych, nie precyzując, czy czekasz na ReferenceType lub ValueType, nie można po prostu zainicjować przypisując null. W takim przypadku należy użyć wartości default keyword.

Spowoduje to zainicjowanie zmiennej na null dla typów odniesienia lub przypisanie 0 dla typów wartości numerycznych. W przypadku struct, zainicjuje każdy element członkowski na jego wartość domyślną.

W zamieszczonym przykładzie porównanie z null pozwala mi założyć, że ta metoda może być używana tylko z ReferenceTypes, jeśli tak jest, najlepiej dodać także ograniczenie class.

+0

Myślę, że w CLR może nie być dobrze zdefiniowanej wartości * do * set (a kompilator C# po prostu wykonuje trasę, aby koder zrobił to zamiast popychania w 'defaultie '(T) gdzieś) - Wydaje mi się, że widziałem ostatnio wpis SO mówiący, że zmienna "slot" * może być dostępna * przez jakiś bezpośredni bajt. –

Powiązane problemy