2011-02-06 2 views
7

Использование непризнанной локальной переменной «модель». Это сообщение об ошибке, которое я получаю. Его право, где я говорю if (model == null). Я не знаю, почему это дает мне ошибку времени компиляции. Кто-то, пожалуйста, помогите.«Использование неназначенной локальной переменной» в общем методе

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

ответ

15

Как указано в ошибке, вы не можете использовать локальную переменную, пока компилятор не сможет доказать, что ему было присвоено значение.

В вашем случае, если ваше условие if является ложным, переменная model никогда не назначается.

Вы можете решить эту проблему путем присвоения ему инициал оцененный первым:

T model = default(T); 

Обратите внимание, что если T тип структура, model == null никогда не может быть правдой.

Вы должны изменить свой код

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

Хорошо, описательный ответ. О-и поздравления :-) –

1

model Поскольку локальная переменная, компилятор дает вам эту ошибку, потому что она назначается только в если заявление. Если условие оператора if неверно, model не будет присвоено значение. Попытайтесь дать ему значение по умолчанию null или добавить инструкцию else и присвоить ей model.

T model = null; 

Локальные переменные не инициализируются автоматически, но переменные экземпляра.

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

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

Компилятор не знает, что назначить, пока вы его не сообщите.

Вместо T model; использовать T model = default(T);

Для получения дополнительной информации: http://msdn.microsoft.com/en-us/library/xwth0h0d(v=vs.80).aspx

редактирования: еще один вариант, чтобы просто переместить новое заявление до вашего десериализации блока. Таким образом, у вас будет либо новый объект, либо десериализованный объект, как и сейчас.

+1

Это не имеет никакого отношения к тому, чтобы быть ссылочным типом. Кроме того, 'T' не является ссылочным типом. – SLaks

+0

@SLaks, я ничего не вижу в сообщении, предполагая, что 'T' не является ссылочным типом. Код, как сейчас, будет работать только для типа значения. Для ссылочных типов ему придется назначить нуль, значение по умолчанию или новый объект. –

+0

Если вы не пишете 'где T: class',' T' не является ссылочным типом. – SLaks

3

При работе с локальными переменными, они всегда должны быть присвоены значения перед тем, как получить доступ.

Причина этого в том, что обычно, когда разработчик игнорирует инициализацию, он полагается на среду выполнения, чтобы присвоить ей значение по умолчанию, но в случае, если он забыл, это может вызвать некоторые ненужные ошибки.

В случае работы с обобщениями, а не уточняя ли вы ожидаете ReferenceType или ValueType, вы не можете просто инициализировать его путем присвоения null. В этом случае вам необходимо использовать default keyword.

Это будет инициализировать переменную null для ссылочных типов или назначить 0 для числовых типов значений. Для structs он инициализирует каждый член по умолчанию.

В приведенном примере сравнение с null позволяет мне предположить, что этот метод может использоваться только для использования с ReferenceTypes, если это так, лучше также добавить ограничение class.

+0

Я думаю, что в CLR не может быть четко заданного значения * до * set (а компилятор C# просто берет на себя путь сделать кодер делать это вместо того, чтобы толкать в 'default (T) 'где-то). Я считаю, что увидев сообщение SO, недавно сказал, что переменный« слот »* может быть доступен * через некоторый прямой байт-код. –

Смежные вопросы