Подтвердить что ты не робот

Ошибка компилятора С# 7 - соответствие шаблону

По какой-то причине M1() вызывает ошибку компилятора, а M2(), что делает то же самое, не вызывает ошибки. Любая идея почему?

Использование false == должно быть таким же, как с использованием оператора not, !.

Использование неназначенной локальной переменной 'i'

class Program {
    static void Main(string[] args) {
        int x = 8;

        M1(x);
        M2(x);
    }  // Main()

    public static void M1(Object obj) {
        if (false == (obj is int i))  // Causes ERROR on WriteLine
            return;

        System.Console.WriteLine(i); // Use of unassigned local variable 'i'
    }

    public static void M2(Object obj) {
        if (!(obj is int i))  // OKAY
            return;

        System.Console.WriteLine(i);
    }
} // class Program
4b9b3361

Ответ 1

Проблема здесь в том, как компилятор обрабатывает "определенно назначенный, когда true". ! инвертирует это; == false нет. Итак, для кода:

if (!(obj is int i))
        return;

System.Console.WriteLine(i);

Компилятор может сделать вывод, что если obj is int i является ложным, ! инвертирует, что, таким образом, return произойдет, если это не int. Поэтому i может быть безопасно "утечка" в следующий код.

Однако те же правила не относятся к == false. Несмотря на то, что семантически идентичен человеческому читателю кода, компилятор рассматривает ! и == false как очень разные вещи. Итак, для:

if (false == (obj is int i))

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

Для обсуждения этого, пожалуйста, см. Неверное "использование неназначенной локальной переменной" для (x is T y) == false.

Мораль истории: избегайте сравнения с false и используйте ! при использовании шаблонов С#.

ИЗМЕНИТЬ

Следует отметить, что == false здесь не является частным случаем. Любое использование == устраняет возможность компилятора определить "определенно назначенный, когда true". Например, следующий код компилируется:

object x = 1;
if (!(x is bool y))
    return 0;

var z = y;

Но добавьте == true, и он больше не делает:

object x = 1;
if (!(x is bool y == true))
    return 0;

var z = y; // error: use of an unassigned variable

EDIT2

Случайно, для тех, кто использует if (expression == false), потому что они находят if (!expression) трудным для чтения, вам может быть интересно узнать, что синтаксис if !(expression) рассматривается для С# 8.

Ответ 2

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

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

var x = obj is int i;
if(x) Console.WriteLine(i);

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

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

if((obj is int i) == false)

здесь == оператор помещает пробел между результатом сопоставления шаблонов и оценивает оператор if, следовательно, ошибку. Я не знаю, почему оператор ! отлично работает, может быть, они оптимизировали эту часть, но забыли оптимизировать это?;)

Я думаю, что это относится к фазе семантического анализа компилятора, его задача - проверить смысл вашего кода и определить, как он выполняется, если что-то не так, если есть возможность поведения undefined или что-то совершенно бессмысленное, он терпит неудачу, и вы получаете ошибку времени компиляции. подробнее о Фазы проектирования компилятора