Как обрабатывать "не все пути кода возвращают значение" , когда логика функции гарантирует возврат

Я полагаю, что самый простой способ объяснить это надуманный пример:

public static int Fail() {
    var b = true;
    if (b) {
        return 0;
    }
}

этот код не будет компилироваться и дает ошибку "не все пути кода возвращают значение", в то время как мы, люди, ясно видим, что это так. Я понимаю почему. Мой вопрос что нужно сделать, чтобы исправить ситуацию. Это может быть что-то вроде этого:

public static int Fail() {
    var b = true;
    if (b) {
        return 0;
    }
    throw new ApplicationException("This code is unreachable... but here we are.");
}

но все это кажется довольно глупым. Есть ли лучший способ? Опять же, этот код является надуманным примером (и может быть уменьшен до return 0). Мой фактический код массивен и сложен, но логически (математическим доказательством) возвращает значение перед попыткой выхода.

6 ответов


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

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

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


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


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

Если вы уверены в своих предположениях, просто добавьте return 0; в конце с комментарием о том, что он никогда не будет достигнут.

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


обычно существует несколько классов программистов:

  1. они вернуться все.
  2. те, кто возвращается только в конце функции / метода.

первый подход:

public static int Fail() {
  var b = true;
  if (b)
    return 0;

  return 1;
}

Я обычно предпочитаю второй подход, так как легче быстро увидеть, где возвращается функция/метод.

public static int Fail() {
  var b = true;
  var returnValue = 1:
  if (b)
    returnValue = 0;

  return returnValue;
}

действительно поздний ответ, но я могу представить себе сценарий, в котором функция не будет знать, что вернуть:

1) выполните шаг за шагом с помощью отладчика

2) Шаг через var b = true;

3) Когда if (b) { достигнуто, put b = false в часы. Он оба вернется false и назначить b = false

4) Шаг за (за if)

5) достигнут конец функции, никакого возврата нет

С этой точки зрения, return is это было необходимо.


у меня был такой код и закрепил ее таким образом. Глядя на ваш пример:

public static int Fail() {
    var b = true;
    if (b) {
        return 0;
    }
    throw new ApplicationException("This code is unreachable... but here we are.");
}

станет

public static int Fail() {
    var b = true;
    if (!b) {
        throw new ApplicationException("This code is unreachable... but here we are.");
    }
    return 0;
}

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