Использование неинициализированной переменной - компилятор не работает - PullRequest
2 голосов
/ 01 марта 2012

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

Компилятор жалуется, что переменная parsed может не инициализироваться в операторе возврата.Я не согласнаКто из нас не прав и почему?

public DateTime? Test(string nextDate)
{
    DateTime parsed;

    if (nextDate != "TBC" && !DateTime.TryParse(nextDate, out parsed))
    {
        throw new Exception();
    }

    if (nextDate == "TBC")
        return null;

    return parsed;
}

Ответы [ 4 ]

6 голосов
/ 01 марта 2012

Нет, компилятор вообще не работает.

Компилятор не предназначен для того, чтобы указывать, что

if (nextDate != "TBC")

и

if (nextDate == "TBC")

являются взаимоисключающими.Он не пытается установить связь между этими двумя условиями.Так что он не может сказать, что вы определенно вызовете DateTime.TryParse(nextDate, out parsed), если вы доберетесь до return parsed;.

По сути, компилятор следует относительно простым правилам для определения определенного назначения(и достижимость).Простые правила легко продумать, легко реализовать и легко кодировать.

К счастью, вы можете упростить свой код и , одновременно компилируя его:

public DateTime? Test(string nextDate)
{
    if (nextDate == "TBC")
    {
        return null;
    }

    DateTime parsed;    
    if (!DateTime.TryParse(nextDate, out parsed))
    {
        throw new Exception();
    }
    return parsed;
}

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

3 голосов
/ 01 марта 2012

Вы оба правы.

Логика проверки неинициализированной переменной просматривает все возможные пути потока управления без более глубокого логического анализа. Эта часть компилятора не заботится о том, что nextDate == "TBC" и nextDate != "TBC" никогда не являются истинными. Так что компилятор прямо из его PoV.

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

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


Я бы переписал вашу функцию так:

public DateTime? Test(string nextDate)
{
    DateTime parsed;

    if (nextDate == "TBC" )
       return null;

    if(!DateTime.TryParse(nextDate, out parsed))
      throw new Exception();

    return parsed;  
}

Но так как вы в любом случае выдает исключение, вы можете использовать Parse вместо TryParse.

3 голосов
/ 01 марта 2012

если nextData == "TBC", ваш TryParse не вызывается, так как все условие в любом случае не может быть истинным.Поэтому parsed не может быть инициализирован.

1 голос
/ 01 марта 2012

as out является частью оператора if, вам необходимо инициализировать значение.

Потому что если satement идет слева направо, и в вашем случае nextDate != "TBC" сначала проверяется, а затем проверяется следующее утверждение.

так что это похоже на

if( fist check)
{
 if(second check)
 {
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...