Почему компилятор ведет себя по-другому с этим кодом?

В C# следующий метод не скомпилирует:

public bool IsItTrue()
{
}

Ошибки компилятора: 'IsItTrue ()': не все пути выполнения кода возвращают значение, которое имеет смысл. Но следующая компиляция без любой проблемы.

public bool IsItTrue()
{
    while (true)
    {
    }
}

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

8
задан Mike Two 23 December 2009 в 14:55
поделиться

3 ответа

Компилятор знает, что второй метод никогда не вернётся.

Если любой из методов когда-либо вернётся при любых обстоятельствах, то он должен вернуть bool.

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

Второй метод никогда не возвращается из-за бесконечного цикла while (true). Если он никогда не возвращает , то не имеет значения, что (если что) никогда не возвращается никогда не возвращается , поэтому компилятор позволит ему скомпилировать его.

Еще несколько примеров, которые компилятор распознает и позволит:

public bool IsItTrue()
{
    throw new Exception("Always thrown!");
}

public bool HowAboutThisOne()
{
    if ((46 - 3) < (27 * 9))
    {
        throw new Exception("Always thrown!");
    }
}
13
ответ дан 5 December 2019 в 10:03
поделиться

Первое хорошо объясняется сообщением об ошибке компилятора.

Второе никогда не возвращает, поэтому никогда не возвращает никаких значений.

Это не одно и то же. В первом примере метод мог вернуть без возврата какого-либо значения вызывающему абоненту -> Ошибка компилятора.

Второй никогда не вернет (компилятор достаточно умен для этого, он понимает, что вы создали бесконечный цикл). Он никогда не войдет в состояние "Хорошо, я дошел до конца метода и не знаю, что возвращать"

.
3
ответ дан 5 December 2019 в 10:03
поделиться

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

Например, рассмотрим две следующие функции.

public bool NoError()
{
    while (true) { }
}

public bool Error()
{
    while (NoError()) { }
}

Как было показано, первая функция не будет выдавать ошибку времени компиляции. Однако, вторая будет, так как компилятор не сможет оценить результат вызова функции NoError(). Это также происходит, если модифицировать NoError(), чтобы всегда возвращать true.

.
1
ответ дан 5 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: