C # 7.0 шаблон соответствия синтаксиса области видимости и назначения переменных - PullRequest
0 голосов
/ 16 марта 2019

Предварительно: Область соответствия переменной шаблона , но я хотел бы узнать больше о поведении присваивания.

Я провел следующий тест.

В F1Кажется, i находится в области видимости, но не назначен, что я могу понять по F2.

Но ситуация в F3 меня действительно озадачивает, потому что это не может быть объяснено F2.

Тогда в F4 это показывает, что ! не имеет никакого эффекта в этой ситуации.

// inside a class
object o = 1;
void F0() { // normal usage
    if(o is int i)
        WriteLine(i);
}
void F1() {
    if (o is int i)
        WriteLine(i);
    else
        WriteLine(i); // Use of unassigned local variable 'i'
    WriteLine(i); // the same as above
}
void F2() {
    int i;
    if (o is int) {
        i = (int)o; // just for simulation because 'as' can't unbox
        WriteLine(i);
    }
    else
        WriteLine(i); // Use of unassigned local variable 'i'
    WriteLine(i); // Use of unassigned local variable 'i'
}
void F3() {
    if (!(o is int i))
        WriteLine(i); // Use of unassigned local variable 'i'
    else
        WriteLine(i); // compile
    WriteLine(i); // Use of unassigned local variable 'i'
}
void F4() {
    _ = !(o is int i);
    Console.WriteLine(i); // Use of unassigned local variable 'i'

    _ = o is int i;
    Console.WriteLine(i); // Use of unassigned local variable 'i'
}

Я могу только заключить, что этот синтаксис обрабатывает if по-другому, что если if condition верно, это будетназначить в области действия if true, в противном случае он будет назначен в области действия if else.

Правильно ли мое понимание? (я полагаю, не

Ответы [ 2 ]

1 голос
/ 16 марта 2019

Из спецификации для шаблонов в C # 7.0 :

Область действия переменных шаблона

Область действия переменной, объявленной в шаблоне, следующая:

  • Если шаблон является меткой регистра, тогда область видимости переменной - блок регистра .

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

  • Если выражение находится в выражениилямбда, его область действия - тело лямбды.
  • Если выражение находится в методе или свойстве с выражением тела, его область действия - тело метода или свойства.
  • Есливыражение находится в предложении when предложения catch, его область действия заключается в том, что предложение catch.
  • Если выражение находится в iteration_statement , его область действия - это простооператор.
  • В противном случае, если expression находится в какой-то другой форме оператора, его область действия - это область действия, содержащая инструкцию.

В целях определения области действия embedded_statement считается находящимся в его собственной области действия.,Например, грамматика для if_statement равна

if_statement
    : 'if' '(' boolean_expression ')' embedded_statement
    | 'if' '(' boolean_expression ')' embedded_statement 'else' embedded_statement
    ;

Так что если управляемый оператор if_statement объявляет переменную шаблона, его область действия ограничивается этим embedded_statement :

if (x) M(y is var z);

В этом случае область действия z представляет собой встроенный оператор M(y is var z);.

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

В C # 7.3 мы добавили следующие контексты, в которых переменная шаблона может быть объявлена: - Есливыражение находится в инициализаторе конструктора , его область действия - инициализатор конструктора и тело конструктора.- Если выражение находится в инициализаторе поля, его областью действия является equals_value_clause , в котором оно появляется.- Если выражение находится в предложении запроса, которое указано для перевода в тело лямбды, его область действия - это просто выражение.

0 голосов
/ 16 марта 2019

Давайте посмотрим ближе на следующее утверждение:

o is int i

Если o можно привести к типу int, то этот оператор вернет true и будет установлена ​​переменная i. Если нет, он вернет false и переменная i не будет инициализирована. Кроме того, использование такого кода в операторах if перемещает переменную во внешнюю область.

Давайте рассмотрим ваши методы:

void F1() {
   if (o is int i)
        WriteLine(i);  // i was initialized, because o is int i returned true
    else
        WriteLine(i); // i was NOT initialized, so you have using of unassigned local variable 'i' here
    WriteLine(i); // the same as above, because i wasn't initialized in all code paths before this statement
}

void F2() {
    int i;
    if (o is int) {
        i = (int)o; // just for simulation because 'as' can't unbox
        WriteLine(i); // i was initialized in previous line
    }
    else
        WriteLine(i); // o is not int, so i wasn't initialized => using of unassigned local variable 'i'
    WriteLine(i); // i wasn't initialized in all code paths, using of unassigned local variable 'i'
}

void F3() {
    if (!(o is int i))
        WriteLine(i); // Using of unassigned local variable 'i' because o can't be casted to int => !(o is int i)
    else
        WriteLine(i); // compile - i was initialized
    WriteLine(i); // you wrote this statement can be compiled, in fact not, because i is not initialized in all code paths
}

void F4() {
    _ = (!(o is int i));
     Console.WriteLine(i); // Use of unassigned local variable 'i', because in case of unsuccessful casting i won't be intialized.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...