Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

7.20Логические выражения

Логическое_выражение — это выражение, которое дает результат типа bool; напрямую или посредством применения оператора operator true в определенных контекстах, как указано далее.

boolean-expression: expression

Логическим_выражением является управляющее условное выражение оператора_if (§8.7.1), оператора_while (§8.8.1), оператора_do (§8.8.2) оператора_for (§8.8.3). Для управляющего выражения оператора?: (§7.14) действуют те же правила, что и для логического_выражения, но из-за приоритетов операторов оно классифицируется как условное_выражение_ИЛИ.

Логическое_выражение должно иметь тип, который может быть неявно преобразован в тип bool или тип, в котором реализуется оператор operator true. Если не выполняется ни одно из этих требований, то возникает ошибка времени привязки.

Если логическое выражение нельзя неявно преобразовать в тип bool, но в этом типе реализуется оператор operator true, то для получения логического значения после вычисления выражения вызывается реализация оператора operator true из этого типа.

Тип структуры DBBool в разделе §11.4.2 является примером типа, в котором реализуется оператор operator true и operator false.

8.Операторы языка

Язык C# содержит множество операторов. Большинство из них будут знакомы разработчикам, имеющим опыт программирования на языках C и C++.

оператор_языка: помеченный_оператор оператор_объявления внедренный_оператор

внедренный_оператор: блок пустой_оператор оператор_выражение оператор_выбора оператор_итераций оператор_перехода оператор_try оператор_checked оператор_unchecked оператор_lock оператор_using оператор_yield

Нетерминальное выражение внедренный_оператор используется для обозначения операторов, входящих в состав других операторов языка. Использование внедренного_оператора вместо обычного оператора_языка позволяет обходиться без операторов объявления и помеченных операторов в этих контекстах. Например:

void F(bool b) { if (b) int i = 44; }

результатом будет ошибка времени компиляции, поскольку для оператора if требуется использовать внедренный_оператор в ветви if, а не оператор_языка. Если бы такой код был разрешен, переменная i стала бы объявленной, но ее нельзя было бы использовать. Следует, однако, отметить, что помещение объявления i в блок делает пример допустимым.

8.1Конечные точки и достижимость

У каждого оператора языка имеется конечная точка. Интуитивно говоря, конечная точка оператора — это позиция, непосредственно следующая за оператором. Правилами выполнения составных операторов (операторов языка, содержащих внедренные операторы) определяется действие, которое предпринимается, когда управление достигает конечной точки внедренного оператора. Например, когда управление достигает конечной точки оператора в блоке, оно передается следующему оператору этого блока.

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

В этом примере

void F() { Console.WriteLine("reachable"); goto Label; Console.WriteLine("unreachable"); Label: Console.WriteLine("reachable"); }

второй вызов функции Console.WriteLine недостижим, потому что он не может быть выполнен ни при каких условиях.

Если компилятором установлен факт недостижимости оператора языка, выдается предупреждение. Недостижимость оператора не рассматривается как ошибка.

Чтобы определить, достижим ли данный оператор языка или конечная точка, компилятор выполняет анализ потока управления в соответствии с правилами достижимости, установленными для каждого оператора. В ходе анализа принимаются во внимание значения константных выражений (§7.19), контролирующих поведение операторов, но возможные значения неконстантных выражений не учитываются. Иными словами, при анализе потока управления считается, что неконстантное выражение данного типа может принимать любое значение этого типа.

В этом примере

void F() { const int i = 1; if (i == 2) Console.WriteLine("unreachable"); }

логическое выражение оператора if является константным выражением, поскольку оба операнда оператора == представляют собой константы. Поскольку константное выражение вычисляется во время компиляции и его значением оказывается false, вызов Console.WriteLine считается недостижимым. Однако если переменную i сделать локальной:

void F() { int i = 1; if (i == 2) Console.WriteLine("reachable"); }

то вызов Console.WriteLine станет достижимым, хотя на самом деле и не будет никогда выполняться.

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

В этом примере

void F(int x) { Console.WriteLine("start"); if (x < 0) Console.WriteLine("negative"); }

достижимость второго вызова Console.WriteLine устанавливается следующим образом:

  • Первый оператор-выражение Console.WriteLine достижим, поскольку блок метода F является достижимым.

  • Конечная точка первого оператора-выражения Console.WriteLine достижима, поскольку сам оператор достижим.

  • Оператор if достижим, поскольку конечная точка первого оператора-выражения Console.WriteLine достижима.

  • Второй оператор-выражение Console.WriteLine достижим, поскольку значением логического выражения оператора if не является константа false.

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

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]