Почему этот метод с параметром 'out' говорит, что он не установлен?
UGH! Ну, я собирался опубликовать это как вопрос, потому что я не знал, почему я вижу ошибку... но, конечно, теперь это так очевидно, когда я ее вижу. Теперь хлопаю себя по голове. Я оставлю это здесь для удовольствия. Посмотри, сможешь ли ты поймать это.
Выполняя TryGetValue для нашего класса WeakDictionary сегодня вечером, я наткнулся на что-то странное. Я получаю ошибку, и я не знаю почему.
Вот код:
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if(_itemStorage.TryGetValue(key, out weakReference))
if(weakReference.TryGetTarget(out value))
return true;
else
value = default(TItem);
return false;
}
Вот ошибка, которую я получаю:
Выходной параметр 'value' должен быть назначен до того, как управление покинет текущий метод.
Для меня это выглядит так, как будто все пути кода устанавливают значение до того, как оно вернется.
Если первое 'if' не выполняется, предложение 'else' устанавливает значение 'value'.
Однако, если первое "если" проходит, не означает, что следующая строка "weakReference.TryGetTarget" установила "значение" по той же самой причине, о которой меня предупреждают (то есть "TryGetTarget" имеет сам параметр "out", поэтому он тоже должен установить свой параметр out, прежде чем он вернется)?
Как я уже сказал, мне не хватало чего-то очевидного. (Мне нужно поспать!)
3 ответа
Проблема заключается в том, что если ваш первый оператор if потерпит неудачу, вы останетесь без инициализации значения.
По сути, вам не хватает фигурных скобок в вашем if
заявление, которое сделает else
Заявление правильно приложить к правильному if
:
if (_itemStorage.TryGetValue(key, out weakReference))
{
if (weakReference.TryGetTarget(out value))
return true;
}
Документы проясняют это:
Оператор или операторы в тогда-утверждении и в другом-выражении могут быть любого вида, включая другой оператор if, вложенный в исходный оператор if. Во вложенных операторах if каждое предложение else принадлежит последнему, если этому не соответствует соответствующий else.
Это значит, что твой else
пункт прилагается к внутреннему if
заявление, а не внешнее.
Вы также можете переписать это как:
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if (_itemStorage.TryGetValue(key, out weakReference))
return weakReference.TryGetTarget(out value);
value = default(TItem);
return false;
}
Удалить else
заявление.
Фактически так же, как ответ @Yuval, но мне нравится удалять код.
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if(_itemStorage.TryGetValue(key, out weakReference))
if(weakReference.TryGetTarget(out value))
return true;
value = default(TItem);
return false;
}
Также обратите внимание, что if(c1) if(c2)
эквивалентно if (c1 && c2)
; который читает лучше и не будет вашей проблемы.
Ваш код компилируется так:
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if (_itemStorage.TryGetValue(key, out weakReference))
{
if (weakReference.TryGetTarget(out value))
{
return true;
}
else
{
value = default(TItem);
}
}
return false;
}
В этом коде value
переменная не устанавливается, если первый if
ложно
То, что вы действительно хотели - и думали, что получили - было это:
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if (_itemStorage.TryGetValue(key, out weakReference))
{
if (weakReference.TryGetTarget(out value))
{
return true;
}
}
else
{
value = default(TItem);
}
return false;
}
Это опасность не указания скобок и предположения, что положение столбца else
было правильно.