2015-09-20 9 views
0

UGH! Ну, я был собираюсь опубликовать это как вопрос, потому что я не знал, почему я видел ошибку ... но, конечно, теперь это так очевидно, когда я это вижу. Похлопывая себя в голову сейчас. Хотя я оставлю его здесь для удовольствия. Посмотрите, можете ли вы это поймать.Почему этот метод с параметром «out» говорит, что он не установлен?

При внедрении 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; 
} 

Вот ошибка я получаю:

Выездное параметр «значение» должен быть назначен прежде чем управление покидает текущий метод.

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

Если первое «если» не выполнено, предложение «else» устанавливает значение «.

Если первая «если» проходит, однако, следующая строка «weakReference.TryGetTarget» устанавливает «значение» по той же самой причине, о которой я предупреждаю (т. Е. «TryGetTarget» имеет параметр «out» сам, поэтому он тоже должен установить свой параметр внутри, прежде чем он вернется)?

Как я уже сказал, мне не хватало чего-то очевидного. (Мне нужно спать!)

+0

В конце концов, это действительно просто опечатка. Скажите, что вы будете делать с постоянными предпочтениями (и автоматическим отступом кода), но именно поэтому я их использую. – user2864740

+0

Я только что попробовал это в нескольких версиях Visual Studio, и он соответствующим образом откладывает инструкцию 'else' в соответствии со вторым оператором' if', делая очевидным, что он принадлежит этому. Вы используете другую среду IDE? –

+0

Да, но эта простая опечатка сорвала меня на проклятый полчаса, исследуя ее, прежде чем я ударил лоб, поняв, что я идиот! :) – MarqueIV

ответ

7

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

В принципе, вы упускаете фигурные скобки в вашем if заявления, которое сделает else заявления правильно прикрепить к правильным if:

if (_itemStorage.TryGetValue(key, out weakReference)) 
{ 
    if (weakReference.TryGetTarget(out value)) 
     return true; 
} 

The docs ясно это:

Оператор или операторы в then-statement и else-statement могут быть любого типа, включая другой оператор if , вложенный в исходную инструкцию if. Во вложенных операциях if каждый предложение else принадлежит последнему, если у него нет соответствующего else.

Это означает, что ваше положение else придается внутреннему if заявление, вместо Outter.

Вы также можете переписать это так:

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

Опускание фигурных скобок не влияет на код образца, так как каждый условный оператор сопровождается одним утверждением. –

+1

@SaebAmini Попробуйте сами и посмотрите. –

+0

Первый, как тот, который у меня есть в моем ответе. Второй будет избыточно устанавливать 'значение' дважды, если оба оператора' if' проваливаются. –

4

Удалите 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); который лучше читает и не будет иметь проблемы.

2

Ваш код компилируется как это:

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 было правильным.

+0

Ура, «очевидный» синтаксический анализ, если, наконец, указывается! – user2864740