Объявления локальных констант — КиберПедия 

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

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

Объявления локальных констант

2017-10-16 303
Объявления локальных констант 0.00 из 5.00 0 оценок
Заказать работу

Объявление локальной константы объявляет одну или несколько локальных констант.

local-constant-declaration:
const type constant-declarators

constant-declarators:
constant-declarator
constant-declarators, constant-declarator

constant-declarator:
identifier = constant-expression

Тип в объявлении локальной константы задает тип констант, представленных в объявлении. За типом следует список деклараторов констант, каждый из которых представляет новую константу. Декларатор константы состоит из идентификатора, определяющего имя константы, за которым следуют лексема = и константное выражение (§7.19), задающее значение константы.

Тип и константное выражение в объявлении локальной константы подчиняются тем же правилам, что и в объявлении члена-константы (§10.4).

Значение локальной константы получается из выражения с использованием простого имени (§7.6.2).

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

Объявление нескольких локальных констант эквивалентно нескольким объявлениям одиночных констант одного и того же типа.

Операторы-выражения

Оператор выражение служит для вычисления данного выражения. Значение, вычисленное выражением (если оно получено), не сохраняется.

expression-statement:
statement-expression;

statement-expression:
invocation-expression
object-creation-expression
assignment
post-increment-expression
post-decrement-expression
pre-increment-expression
pre-decrement-expression
await-expression

Не все выражения разрешается использовать как операторы языка. В частности, такие выражения, как x + y и x == 1, которые просто вычисляют значение (впоследствии отбрасываемое), недопустимы в качестве операторов языка.

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

Операторы выбора

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

selection-statement:
if-statement
switch-statement

Оператор if

Оператор if выбирает оператор языка для выполнения на основании значения логического выражения.

if-statement:
if (boolean-expression) embedded-statement
if (boolean-expression) embedded-statement else embedded-statement

Компонент else относится к лексикографически ближайшему предшествующему компоненту if, разрешенному правилами синтаксиса. Так, оператор if в виде

if (x) if (y) F(); else G();

равнозначно

if (x) {
if (y) {
F();
}
else {
G();
}
}

Оператор if выполняется следующим образом.

· Вычисляется логическое выражение (§7.20).

· Если результатом логического выражения является true, управление передается первому внедренному оператору. Если управление достигает конечной точки этого оператора, после этого управление передается в конечную точку оператора if.

· Если результатом логического выражения является false и в операторе имеется компонент else, управление передается второму внедренному оператору. Если управление достигает конечной точки этого оператора, после этого управление передается в конечную точку оператора if.

· Если результатом логического выражения является false и компонент else отсутствует, управление передается в конечную точку оператора if.

Первый внедренный оператор в составе оператора if считается достижимым, если оператор if достижим и значением логического выражения не является константа false.

Второй внедренный оператор оператора if (если он имеется) достижим, если оператор if достижим и значением логического выражения не является константа true.

Конечная точка оператора if достижима, если достижима конечная точка по крайней мере одного из его внедренных операторов. Кроме того, конечная точка оператора if без компонента else считается достижимой, если оператор if достижим и значением логического выражения не является константа true.

Оператор switch

Оператор switch выбирает для выполнения список операторов, метка которого соответствует значению switch-выражения.

switch-statement:
switch (expression) switch-block

switch-block:
{ switch-sectionsopt }

switch-sections:
switch-section
switch-sections switch-section

switch-section:
switch-labels statement-list

switch-labels:
switch-label
switch-labels switch-label

switch-label:
case constant-expression:
default:

Оператор switch состоит из ключевого слова switch, за которым следуют выражение в скобках (так называемое switch-выражение) и затем блок switch. Блок switch состоит из произвольного (возможно, нулевого) числа разделов switch, заключенных в фигурные скобки. Каждый раздел switch состоит из одной или нескольких меток switch и следующего за ними списка операторов (§8.2.1).

Определяющий тип оператора switch устанавливается switch-выражением.

· Если типом switch-выражения является sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string или перечисляемый тип, или если это обнуляемый тип, соответствующий одному из перечисленных типов, то он считается определяющим типом оператора switch.

· В противном случае должно существовать ровно одно пользовательское неявное преобразование (§6.4) типа switch-выражения в один из следующих возможных определяющих типов: sbyte, byte, short, ushort, int, uint, long, ulong, char, string или обнуляемый тип, соответствующий одному из этих типов.

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

Константное выражение каждого раздела case должно представлять значение, тип которого допускает неявное преобразование (§6.1) в определяющий тип оператора switch. Ошибка времени компиляции возникает, если несколько меток case в одном операторе switch задают одно и то же константное значение.

В операторе switch может быть не более одной метки default.

Оператор switch выполняется следующим образом.

· Вычисляется switch-выражение, которое преобразуется в определяющий тип.

· Если одна из констант, указанных в метке case того же оператора switch, совпадает со значением switch-выражения, управление передается списку операторов, следующему за такой меткой case.

· Если ни одна из констант, указанных в метках case того же оператора switch, не совпадает со значением switch-выражения и при этом имеется метка default, управление передается списку операторов, следующему за меткой default.

· Если ни одна из констант, указанных в метках case того же оператора switch, не совпадает со значением switch-выражения и метка default отсутствует, управление передается в конечную точку оператора switch.

Если конечная точка списка операторов в разделе switch достижима, распознается ошибка времени компиляции. Это так называемое правило «запрета последовательного выполнения». Пример:

switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}

является допустимым, поскольку в нем нет разделов switch с достижимой конечной точкой. В отличие от языков C и C++, при выполнении раздела switch не допускается выход в следующий раздел switch, поэтому в примере

switch (i) {
case 0:
CaseZero();
case 1:
CaseZeroOrOne();
default:
CaseAny();
}

возникает ошибка времени компиляции. Если после выполнения одного раздела switch должно следовать выполнение другого раздела switch, необходимо явным образом указывать оператор goto case или goto default:

switch (i) {
case 0:
CaseZero();
goto case 1;
case 1:
CaseZeroOrOne();
goto default;
default:
CaseAny();
break;
}

В разделе switch разрешается использовать несколько меток. Пример:

switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
default:
CaseTwo();
break;
}

является допустимым. Здесь правило запрета последовательного выполнения не нарушается, поскольку метки case 2: и default: входят в один раздел switch.

Правило запрета последовательного выполнения позволяет избежать распространенных ошибок в программах C и C++, вызываемых случайным пропуском оператора break. Кроме того, благодаря этому правилу разделы switch оператора switch можно расставлять в произвольном порядке — это не повлияет на поведение оператора. Например, в вышеприведенном примере можно расположить разделы switch в обратном порядке, и это не отразится на выполнении оператора:

switch (i) {
default:
CaseAny();
break;
case 1:
CaseZeroOrOne();
goto default;
case 0:
CaseZero();
goto case 1;
}

Список операторов раздела switch обычно заканчивается оператором break, goto case или goto default, но в принципе допускается любая конструкция, исключающая достижимость конечной точки списка операторов. Например, оператор while, контролируемый логическим выражением true, никогда не позволит достичь его конечной точки. Аналогично операторы throw и return всегда передают управление в другое место, и их конечные точки также недостижимы. Поэтому следующий пример будет допустимым:

switch (i) {
case 0:
while (true) F();
case 1:
throw new ArgumentException();
case 2:
return;
}

Определяющий тип оператора switch может быть типом string. Пример:

void DoCommand(string command) {
switch (command.ToLower()) {
case "run":
DoRun();
break;
case "save":
DoSave();
break;
case "quit":
DoQuit();
break;
default:
InvalidCommand(command);
break;
}
}

Подобно операторам проверки равенства строк (§7.10.7), оператор switch действует без учета регистра символов и сможет выполнить данный раздел switch только при условии, что строка switch-выражения в точности совпадает с константой метки case.

Если определяющим типом оператора switch является string, в качестве константы метки case разрешается использовать значение null.

Списки операторов в блоке switch могут включать операторы объявления (§8.5). Областью видимости локальной переменной или константы, объявленной в блоке switch, является этот блок switch.

Значение имени, используемого в контексте выражения, должно быть одинаковым в пределах блока switch (§7.6.2.1).

Список операторов в разделе switch считается достижимым, если оператор switch является достижимым и соблюдено по крайней мере одно из следующих условий.

· Значение switch-выражения не является константой.

· Значением switch-выражения является константа, совпадающая с одной из меток case в разделе switch.

· Значением switch-выражения является константа, не совпадающая ни с одной из меток case, и в разделе switch имеется метка default.

· На метку switch раздела switch ссылается доступный оператор goto case или goto default.

Конечная точка оператора switch считается достижимой, если соблюдено по крайней мере одно из следующих условий.

· Оператор switch содержит доступный оператор break, осуществляющий выход из оператора switch.

· Оператор switch является достижимым, значение switch-выражения не является константой и метка default отсутствует.

· Оператор switch является достижимым, значением switch-выражения является константа, не совпадающая ни с одной из меток case, и метка default отсутствует.

Операторы итераций

Оператор итераций повторно выполняет один и тот же внедренный оператор.

iteration-statement:
while-statement
do-statement
for-statement
foreach-statement

Оператор while

Оператор while выполняет внедренный оператор несколько раз (возможно, ни разу) в зависимости от соблюдения условия.

while-statement:
while (boolean-expression) embedded-statement

Оператор while выполняется следующим образом.

· Вычисляется логическое выражение (§7.20).

· Если результатом логического выражения является true, управление передается внедренному оператору. Если управление достигает конечной точки внедренного оператора (возможно, в результате выполнения оператора continue), управление передается в начало оператора while.

· Если значением логического выражения является false, управление передается в конечную точку оператора while.

В операторе while внутри внедренного оператора можно использовать оператор break (§8.9.1) для передачи управления в конечную точку оператора while (т. е. для завершения итераций внедренного оператора), а также оператор continue (§8.9.2) для передачи управления в конечную точку внедренного оператора (для выполнения еще одной итерации оператора while).

Внедренный оператор в составе оператора while считается достижимым, если оператор while достижим и значением логического выражения не является константа false.

Конечная точка оператора while считается достижимой, если соблюдено по крайней мере одно из следующих условий.

· Оператор while содержит доступный оператор break, осуществляющий выход из оператора while.

· Оператор while является достижимым и значение логического выражения отлично от константы true.

Оператор do

Оператор do выполняет внедренный оператор один или несколько раз в зависимости от соблюдения условия.

do-statement:
do embedded-statement while (boolean-expression);

Оператор do выполняется следующим образом.

· Управление передается внедренному оператору.

· Если управление достигает конечной точки внедренного оператора (возможно, в результате выполнения оператора continue), вычисляется логическое выражение (§7.20). Если результатом логического выражения является true, управление передается в начало оператора do. В противном случае управление передается в конечную точку оператора do.

В операторе do внутри внедренного оператора можно использовать оператор break (§8.9.1) для передачи управления в конечную точку оператора do (т. е. для завершения итераций внедренного оператора), а также оператор continue (§8.9.2) для передачи управления в конечную точку внедренного оператора.

Внедренный оператор в операторе do считается достижимым, если оператор do является достижимым.

Конечная точка оператора do считается достижимой, если соблюдено по крайней мере одно из следующих условий.

· Оператор do содержит доступный оператор break, осуществляющий выход из оператора do.

· Конечная точка внедренного оператора достижима и значение логического выражения отлично от константы true.

Оператор for

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

for-statement:
for (for-initializeropt; for-conditionopt; for-iteratoropt) embedded-statement

for-initializer:
local-variable-declaration
statement-expression-list

for-condition:
boolean-expression

for-iterator:
statement-expression-list

statement-expression-list:
statement-expression
statement-expression-list, statement-expression

Инициализатор for (если он задан) состоит из объявления локальной переменной (§8.5.1) или из списка выражений операторов (§8.6), разделенных запятыми. Область видимости локальной переменной, объявленной инициализатором for, начинается с декларатора локальной переменной и заканчивается вместе с внедренным оператором. В область видимости включаются условие for и итератор for.

Условие for (если оно задано) должно быть логическим выражением (§7.20).

Итератор for (если он задан) состоит из списка выражений операторов (§8.6), разделенных запятыми.

Оператор for выполняется следующим образом.

· Если задан инициализатор for, инициализаторы переменных или выражения операторов выполняются в порядке их записи. Этот шаг выполняется только один раз.

· Если задано условие for, оно проверяется.

· Если условие for отсутствует или результатом его вычисления является true, управление передается внедренному оператору. Если управление достигает конечной точки внедренного оператора (возможно, в результате выполнения оператора continue), после этого последовательно вычисляются выражения итератора for (если они заданы), а затем выполняется следующая итерация, начиная с проверки условия for (см. выше).

· Если условие for задано и результатом его вычисления является false, управление передается в конечную точку оператора for.

В операторе for внутри внедренного оператора можно использовать оператор break (§8.9.1) для передачи управления в конечную точку оператора for (т. е. для завершения итераций внедренного оператора), а также оператор continue (§8.9.2) для передачи управления в конечную точку внедренного оператора (для выполнения итератора for и еще одной итерации оператора for, начиная с условия for).

Внедренный оператор в операторе for считается достижимым, если соблюдено одно из следующих условий.

· Оператор for является достижимым и условие for отсутствует.

· Оператор for является достижимым, условие for задано и его значение отлично от константы false.

Конечная точка оператора for считается достижимой, если соблюдено по крайней мере одно из следующих условий.

· Оператор for содержит доступный оператор break, осуществляющий выход из оператора for.

· Оператор for является достижимым, условие for задано и его значение отлично от константы true.

Оператор foreach

Оператор foreach осуществляет перечисление элементов коллекции, выполняя внедренный оператор для каждого элемента коллекции.

foreach-statement:
foreach (local-variable-type identifier in expression) embedded-statement

Тип и идентификатор в каждом операторе foreach объявляют итерационную переменную оператора. Если тип локальной переменной задан идентификатором var, и в области видимости не существует типа именованного var, говорят, что это неявно типизированная итерационная переменная, и в качестве ее типа принимается тип элементов оператора foreach, как описано ниже. Итерационная переменная соответствует локальной переменной, доступной только на чтение, область видимости которой охватывает внедренный оператор. В ходе выполнения оператора foreach итерационная переменная представляет элемент коллекции, для которого в данный момент выполняется итерация. Если внедренный оператор пытается изменить итерационную переменную (путем присваивания или с помощью операторов ++ и ‑‑) или передать ее как параметр ref или out, возникает ошибка времени компиляции.

Далее интерфейсы IEnumerable, IEnumerator, IEnumerable<T> и IEnumerator<T> для краткости называются соответствующими типами из пространств имен System.Collections и System.Collections.Generic.

Во время компиляции оператора foreach сначала определяется тип коллекции, тип перечислителя и тип элементов для выражения. Это происходит следующим образом.

· Если типом X выражения является тип массива, производится неявное преобразование ссылочного типа из X в интерфейс IEnumerable (поскольку System.Array реализует этот интерфейс). В качестве типа коллекции принимается интерфейс IEnumerable, в качестве типа перечислителя — интерфейс IEnumerator и в качестве типа элементов — тип элементов типа массива X.

· Если тип X выражения имеет модификатор dynamic, существует неявное преобразование из выражения в интерфейс IEnumerable (§6.1.8). В качестве типа коллекции принимается интерфейс IEnumerable, в качестве типа перечислителя — интерфейс IEnumerator. Если идентификатор var представлен как тип локальной переменной, то типом элемента будет dynamic, в противном случае – object.

· В противном случае следует определить, существует ли для типа X соответствующий метод GetEnumerator.

o Выполняется поиск членов для типа X с идентификатором GetEnumerator без использования аргументов типа. Если поиск членов не дает результата, или дает неоднозначный результат, или находит член, не являющийся группой методов, следует проверить наличие перечислимого интерфейса, как описано ниже. Рекомендуется выдавать предупреждение, если результатом поиска членов является что-либо, кроме группы методов или отсутствия совпадений.

o Выполняется разрешение перегрузки с использованием результирующей группы методов и пустого списка аргументов. Если разрешение перегрузки не позволяет получить применимые методы, дает неоднозначный результат или приводит к единственному наилучшему методу, который описан как статический или не открытый, следует проверить наличие перечислимого интерфейса, как описано ниже. Рекомендуется выдавать предупреждение, если результатом разрешения перегрузки является что-либо, кроме однозначно определенного открытого метода экземпляра или отсутствия применимых методов.

o Если тип возвращаемого значения E метода GetEnumerator не является типом класса, структуры или интерфейса, возникает ошибка, и больше никакие действия не выполняются.

o Выполняется поиск членов для типа E с идентификатором Current без использования аргументов типа. Если поиск членов не дает результата, приводит к ошибке или находит что-либо, кроме открытого свойства экземпляра, разрешающего чтение, возникает ошибка, и больше никакие действия не выполняются.

o Выполняется поиск членов для типа E с идентификатором MoveNext без использования аргументов типа. Если поиск членов не дает результата, приводит к ошибке или находит что-либо, кроме группы методов, возникает ошибка, и больше никакие действия не выполняются.

o Выполняется разрешение перегрузки для группы методов с использованием пустого списка аргументов. Если разрешение перегрузки не позволяет получить применимые методы, дает неоднозначный результат или приводит к единственному наилучшему методу, который описан как статический или не открытый либо возвращает значение типа, отличного от bool, возникает ошибка, и больше никакие действия не выполняются.

o В качестве типа коллекции принимается X, в качестве типа перечислителя — E, в качестве типа элементов — тип свойства Current.

· В противном случае проверяется наличие перечислимого интерфейса.

o Если среди всех типов Ti, для которых существует неявное преобразование из X в IEnumerable<Ti>, существует уникальный тип T и этот тип T не является dynamic, а для всех остальных типов Ti имеется неявное преобразование из IEnumerable<T> в IEnumerable<Ti>, то в качестве типа коллекции принимается интерфейс IEnumerable<T>, в качестве типа перечислителя — интерфейс IEnumerator<T>, и в качестве типа элементов — тип T.

o Если таких типов T несколько, возникает ошибка, и больше никакие действия не выполняются.

o Если существует неявное преобразование типа X в интерфейс System.Collections.IEnumerable, в качестве типа коллекции принимается этот интерфейс, в качестве типа перечислителя — интерфейс System.Collections.IEnumerator и в качестве типа элементов — тип object.

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

Если описанная выше процедура завершается успешно, она дает однозначно определенный результат: тип коллекции C, тип перечислителя E и тип элементов T. После этого оператор foreach, заданный в виде

foreach (V v in x) внедренный оператор

развертывается следующим образом:

{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
внедренный_оператор
}
}
finally {
… // Ликвидация e
}
}

Переменная e невидима и недоступна для выражения x, внедренного оператора и любого другого исходного кода программы. Переменная v доступна только для чтения во внедренном операторе. Если не определено явное преобразование (§6.2) типа T (типа элементов) в V (тип локальной переменной в операторе foreach), возникает ошибка, и больше никакие действия не выполняются. Если значение x равно null, во время выполнения возникает исключение System.NullReferenceException.

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

Размещение переменной v внутри цикла важно для определения способа ее фиксации анонимной функцией, которая возникает во внедренном операторе.

Пример:

int[] values = { 7, 9, 13 };
Action f = null;

foreach (var value in values)
{
if (f == null) f = () => Console.WriteLine("First value: " + value);
}

f();

Если бы переменная v была объявлена за пределами цикла, она бы совместно использовалась всеми итерациями и ее значение после завершения цикла for стало окончательным значением — 13, которое было бы выведено на печать в результате вызова f. Вместо этого, поскольку каждая итерация имеет собственную переменную v, переменная, зафиксированная функцией f в первой итерации, будет по-прежнему содержать значение 7, которое и выводится на печать. (Примечание. В более ранних версиях C# переменная v объявлялась за пределами цикла while.)

Тело блока finally строится по следующим правилам.

· Если существует неявное преобразование E в интерфейс System.IDisposable, то

o Если E является необнуляемым типом значений, предложение finally развертывается в семантический эквивалент следующего:

finally {
((System.IDisposable)e).Dispose();
}

o В противном случае предложение finally развертывается в семантический эквивалент следующего:

finally {
if (e!= null) ((System.IDisposable)e).Dispose();
}

Исключение составляют ситуации, когда E является типом значения, или же параметром типа, экземпляром которого оказывается тип значения; в этих случаях приведение e к System.IDisposable не сопровождается упаковкой.

· Если E является запечатанным типом, предложение finally развертывается в пустой блок:

finally {
}

· В противном случае предложение finally развертывается следующим образом:

finally {
System.IDisposable d = e as System.IDisposable;
if (d!= null) d.Dispose();
}

Локальная переменная d невидима или недоступна для любого пользовательского кода. В частности, она не вступает в конфликты с другими переменными, чьи области видимости включают блок finally.

Оператор foreach обходит элементы массива в следующем порядке. Элементы одномерных массивов обходятся в порядке возрастания индекса, начиная с индекса 0 и заканчивая индексом Length – 1. Элементы многомерных массивов обходятся сначала по возрастанию индексов самого правого измерения, затем по возрастанию индексов следующего измерения слева и так далее до самого левого измерения.

В следующем примере выводится каждое значение двумерного массива в порядке следования элементов:

using System;

class Test
{
static void Main() {
double[,] values = {
{1.2, 2.3, 3.4, 4.5},
{5.6, 6.7, 7.8, 8.9}
};

foreach (double elementValue in values)
Console.Write("{0} ", elementValue);

Console.WriteLine();
}
}

Вывод выглядит следующим образом:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

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

int[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);

в качестве типа n неявно принимается int — тип элементов массива numbers.

Операторы перехода

Операторы перехода осуществляют безусловную передачу управления.

jump-statement:
break-statement
continue-statement
goto-statement
return-statement
throw-statement

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

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

Выполнение оператора перехода усложняется при наличии сопутствующих операторов try. В отсутствие таких операторов try оператор перехода выполняет безусловную передачу управления своей цели. При его использовании вместе с операторами try схема выполнения становится более сложной. Если оператор перехода производит выход из одного или нескольких блоков try, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех сопутствующих операторов try.

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

using System;

class Test
{
static void Main() {
while (true) {
try {
try {
Console.WriteLine("Before break");
break;
}
finally {
Console.WriteLine("Innermost finally block");
}
}
finally {
Console.WriteLine("Outermost finally block");
}
}
Console.WriteLine("After break");
}
}

перед передачей управления в цель оператора перехода выполняются блоки finally, соответствующие двум операторам try.

Вывод выглядит следующим образом:

Before break
Innermost finally block
Outermost finally block
After break

Оператор break

Оператор break осуществляет выход из ближайшего включающего оператора switch, while, do, for или foreach.

break-statement:
break;

Целью оператора break является конечная точка ближайшего содержащего оператора switch, while, do, for или foreach. Если оператор break не содержится ни в одном операторе switch, while, do, for или foreach, возникает ошибка времени компиляции.

Если несколько операторов switch, while, do, for или foreach вложены друг в друга, оператор break применяется только к самому внутреннему из них. Для передачи управления с переходом через несколько уровней вложенности следует использовать оператор goto (§8.9.3).

Оператор break не дает возможности выйти из блока finally (§8.10). Если оператор break встречается внутри блока finally, цель оператора break должна находиться в том же блоке finally, в противном случае возникнет ошибка времени компиляции.

Оператор break выполняется следующим образом.

· Если оператор break выполняет выход из одного или нескольких блоков try, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех сопутствующих операторов try.

· Управление передается цели оператора break.

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

Оператор continue

Оператор continue начинает новую итерацию ближайшего содержащего оператора while, do, for или foreach.

continue-statement:
continue;

Целью оператора continue является конечная точка внедренного оператора в составе ближайшего содержащего оператора while, do, for или foreach. Если оператор continue не содержится ни в одном операторе while, do, for или foreach, возникает ошибка времени компиляции.

Если несколько операторов while, do, for или foreach вложены друг в друга, оператор continue применяется только к самому внутреннему из них. Для передачи управления с переходом через несколько уровней вложенности следует использовать оператор goto (§8.9.3).

Оператор continue не дает возможности выйти из блока finally (§8.10). Если оператор continue встречается внутри блока finally, цель оператора continue должна находиться в том же блоке finally, в противном случае возникнет ошибка времени компиляции.

Оператор continue выполняется следующим образом.

· Если оператор continue выполняет выход из одного или нескольких блоков try, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех сопутствующих операторов try.

· Управление передается цели оператора continue.

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

Оператор goto

Оператор goto передает управление оператору, обозначенному меткой.

goto-statement:
goto identifier;
goto case constant-expression;
goto default;

Целью оператора goto идентификатор является помеченный оператор с данной меткой. Если метка с указанным именем не существует в текущей функции-члене или если оператор goto не находится в области видимости метки, возникает ошибка времени компиляции. Это правило позволяет использовать оператор goto для передачи управления за пределы вложенной области видимости, но не внутрь вложенной области видимости. В этом примере

using System;

class Test
{
static void Main(string[] args) {
string[,] table = {
{"Red", "Blue", "Green"},
{"Monday", "Wednesday", "Friday"}
};

foreach (string str in args) {
int row, colm;
for (row = 0; row <= 1; ++row)
for (colm = 0; colm <= 2; ++colm)
if (str == table[row,colm])
goto done;

Console.WriteLine("{0} not found", str);
continue;
done:
Console.WriteLine("Found {0} at [{1}][{2}]", str, row, colm);
}
}
}

оператор goto служит для передачи управления из вложенной области видимости.

Целью оператора goto case является список операторов в ближайшем содержащем операторе switch (§8.7.2), который содержит метку case с данным константным значением. Если оператор goto case не содержится ни в одном операторе switch, или если константное выражение не допускает неявное преобразование (§6.1) в определяющий тип ближайшего объемлющего оператора switch, или если ближайший объемлющий оператор switch не содержит метку case с данным константным значением, возникает ошибка времени компиляции.

Целью оператора goto default является список операторов в ближайшем содержащем операторе switch (§8.7.2), содержащем метку default. Если оператор goto default не содержится ни в одном операторе switch или ближайший содержащий оператор switch не содержит метку default, возникает ошибка времени компиляции.

Оператор goto не дает возможности выйти из блока finally (§8.10). Если оператор goto встречается внутри блока finally, цель оператора goto должна находиться в том же блоке finally, в противном случае возникнет ошибка времени компиляции.

Оператор goto выполняется следующим образом.

· Если оператор goto выполняет выход из одного или нескольких блоков try, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех сопутствующих операторов try.

· Управление передается цели оператора goto.

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

Оператор return

Оператор return возвращает управление текущему объекту, вызвавшему функцию, в которой используется оператор return.

return-statement:
return expressionopt;

Оператор return без выражения может использоваться только в функции-члене, не вычисляющей значение, т. е. в методе с типом результата void (§10.6.10), методе доступа set для свойства или индексатора, в методах доступа add и remove для события, в конструкторе экземпляров, статическом конструкторе или деструкторе.

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

Операторы return можно также применять в выражениях анонимных функций (§7.15) и использовать при определении преобразований, существующих для таких функций.

Включение оператора return в блок finally (§8.10) вызывает ошибку времени компиляции.

Оператор return выполняется следующим образом.

· Если оператор return сопровождается выражением, это выражение вычисляется, и результат неявным способом преобразуется в тип возвращаемого значения члена-функции, содержащей оператор. Результатом преобразования становится значение, возвращенное функцией.

· Если оператор return содержится в одном или нескольких блоках try или catch, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех объемлющих операторов try.

· Если содержащая функция не является асинхронной, управление возвращается объекту, вызвавшему содержащую функцию; ему также возвращается результирующее значение, если оно существует.

· Если содержащая функция является асинхронной, управление возвращается текущему вызывающему объекту; при наличии результирующего значения оно записывается в возвращаемую задачу, как описано в разделе §10.14.1.

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

Оператор throw

Оператор throw вызывает исключение.

throw-statement:
throw expressionopt;

Оператор throw с выражением генерирует значение, получаемое в результате вычисления выражения. Выражение должно представлять значение с типом класса System.Exception, или с типом класса, производным от System.Exception, или с типом параметра типа, чьим эффективным базовым классом яв


Поделиться с друзьями:

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

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

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.168 с.