C #: не все пути кода возвращают значение и недоступный код? - PullRequest
2 голосов
/ 07 августа 2011

Эй, у меня есть этот код, и я проверяю, может ли игрок удалить «Предмет» из своего инвентаря. «Инвентарь» - это отсортированный словарь (Item, int) (подзапрос: НУЖЕН ли мне отсортированный словарь, чтобы иметь возможность доступа к элементам в нем с индексным номером ??), а Item - это класс.

     public bool CanRemoveFromItemInventory(string item)
    {
        bool temp = false;
        if (ItemInventory.Count() <= 0)
        {
            return false;
        }
        else if (ItemInventory.Count() > 0)
        {
            for (int b = 0; b < ItemInventory.Count(); b++)
            {
                Item i = ItemInventory.Keys.ElementAt(b);
                if (i.GetName().Equals(item) && ItemInventory[i] >= 1)
                {
                    temp = true;
                }
                else
                {
                    temp = false;
                }

                if (!temp)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
        else
        {
            return temp;

         }
    }

Ответы [ 3 ]

6 голосов
/ 07 августа 2011

Компилятор не пытается понять логику - он просто применяет правила.Насколько это возможно, возможно, что цикл for выполняется ноль раз, поэтому в среднем блоке отсутствует возвращаемое значение:

    else if (ItemInventory.Count() > 0)
    {
        for (int b = 0; b < ItemInventory.Count(); b++)
        {
              // ... this always returns something
        }
        // BUT STILL NEED TO EITHER RETURN OR THROW HERE
    }

действительно, это правильно в этом - злой недовольный мог бы написать метод Count(), который возвращает разные значения при каждом вызове (или представить менее злой сценарий - гонку потока / мутацию данных).

Пожалуй, самое простое «исправление» здесь - изменить:

    else
    {
        return temp;
    }

на просто:

    return temp;

, тогда оно будет применяться ко всем ветвям.

2 голосов
/ 07 августа 2011

Поместите возврат за цикл for:

for (int b = 0; b < ItemInventory.Count(); b++) {
     Item i = ItemInventory.Keys.ElementAt(b);
     if (i.GetName().Equals(item) && ItemInventory[i] >= 1) {
         temp = true;
         break;
     }
}
return temp;

Причина: если Count () равен 0, цикл for никогда не будет выполнен, и, таким образом, вы никогда не повернетесь. Хотя это может быть маловероятно (в конце концов, вы проверяете, что Count больше 0). компилятор не может определить это, потому что Count () может быть изменен между проверкой if и циклом for. Компилятор не может определить это (см. « Проблема останова »)

2 голосов
/ 07 августа 2011

Компилятор замечает, что после цикла for нет оператора return. Компилятор не может доказать, что путь к коду никогда не покинет (или даже не войдет) в цикл for, и поэтому он ожидает выполнения оператора return через некоторое время после цикла. Однако на этом пути нет оператора return.

Что касается ошибки недостижимого кода, вам необходимо добавить комментарий к строке, на которую он жалуется.


Обновление: похоже, вы собираетесь что-то вроде этого:

public bool CanRemoveFromItemInventory(string item)
{
    var pair = ItemInventory.FirstOrDefault(pair => pair.Key.GetName() == item);

    return pair != null && pair.Value >= 1;
}

Текущая версия вашего кода потерпит неудачу, если первый элемент в списке инвентаря не тот, который вы ищете. Другими словами, даже если вы исправите ошибки компилятора, ваш код все равно будет работать неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...