Некорректное использование ошибки компилятора неинициализированной переменной - PullRequest
0 голосов
/ 24 августа 2018

Я только что столкнулся со случаем, когда Visual Studio сообщает, что мой код может привести к доступу к неинициализированной переменной, но правила булевой логики гласят, что это невозможно здесь.

Я упростил код для визуализации проблемы, в данном случае для x:

static void Main(string[] args)
{
    IDictionary<String, MyType> dictionary = null;
    if (new Random().Next() % 2 == 0)
    {
        dictionary = new Dictionary<string, MyType>();
        dictionary.Add("xyz", MyType.Whatever);
        dictionary.Add("abc", MyType.DontCare);
    }

    var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;
}

enum MyType
{
    None,
    Whatever,
    DontCare
}

В случае, если dictionary не инициализирован, он равен нулю, в результате чего ?? оценивает троичный оператор в false. Это единственный случай, когда x не будет инициализирован, но я получаю сообщение об ошибке для x в истинном случае троичного оператора.

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

Это известное поведение или ошибка?

РЕДАКТИРОВАТЬ: Просто чтобы уточнить, я знаю, как решить проблему. Я был просто немного удивлен, столкнувшись с этой ошибкой, поскольку описанная проблема с доступом к неинициализированному x никогда не произойдет в соответствии с булевой логикой.

РЕДАКТИРОВАТЬ: Использование полной, если не меняет проблему:

static void Main(string[] args)
{
    ...

    MyType myType;
    if (dictionary?.TryGetValue("abc", out var x) ?? false)
    {
        myType = x; // <-- error still occurs here
    }
    else
    {
        myType = MyType.None;
    }
}

1 Ответ

0 голосов
/ 24 августа 2018

Проблема заключается в x в этой строке:

var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;

Поскольку у вас есть оператор распространения нуль (?.), x никогда не будет назначено, когда dictionary имеет значение null.Вы должны убрать x как отдельную переменную над var со значением по умолчанию.

MyType x = MyType.None;

var myType = dictionary?.TryGetValue("abc", out x) ?? false ? x : MyType.None;

Статический компилятор просто не достаточно умен, чтобы понять, что оператор распространения нуль приведет кэто выражение всегда возвращает false (и, следовательно, x никогда не используется).Это не просто обрабатывает оператор так, как если бы он мог.

Как вы можете видеть на странице Github языка C #, существует запрос активной функции , позволяющий компилятору выяснить результат выполнения команды.Нулевой оператор распространения.

...