Страница 46 из 502
<b> break; </b>
<b> case 'C':</b>
<b> Console.WriteLine("ch содержит С"); </b>
<b> break; </b>
<b> case 'D' :</b>
<b> Console.WriteLine("ch содержит D"); </b>
<b> break; </b>
<b> case 'E':</b>
<b> Console.WriteLine("ch содержит E"); </b>
<b> break;</b>
<b> }</b>
<b> }</b>
<b>}</b>
Вот какой результат дает выполнение этой программы.
<b>ch содержит А </b>
<b>ch содержит В </b>
<b>ch содержит С </b>
<b>ch содержит D </b>
<b>ch содержит Е</b>
Обратите в данном примере внимание на отсутствие ветви default в операторе switch. Напомним, что ветвь default не является обязательной. Когда она не нужна, ее можно просто опустить.
Переход последовательности операторов, связанных с одной ветвью case, в следующую ветвь case считается ошибкой, поскольку в C# должно непременно соблюдаться правило недопущения "провалов" в передаче управления ходом выполнения программы. Именно поэтому последовательность операторов в каждой ветви case оператора switch оканчивается оператором break. (Избежать подобных "провалов", можно также с помощью оператора безусловного перехода goto, рассматриваемого далее в этой главе, но для данной цели чаще применяется оператор break.) Когда в последовательности операторов отдельной ветви case встречается оператор break, происходит выход не только из этой ветви, но из всего оператора switch, а выполнение программы возобновляется со следующего оператора, находящегося за пределами оператора switch. Последовательность операторов в ветви default также должна быть лишена ''провалов", поэтому она завершается, как правило, оператором break.
Правило недопущения "провалов" относится к тем особенностям языка С#, которыми он отличается от С, C++ и Java. В этих языках программирования одна ветвь case может переходить (т.е. "проваливаться") в другую. Данное правило установлено в C# для ветвей case по двум причинам. Во-первых, оно дает компилятору возможность свободно изменять порядок следования последовательностей операторов из ветвей case для целей оптимизации. Такая реорганизация была бы невозможной, если бы одна ветвь case могла переходить в другую. И во-вторых, требование завершать каждую ветвь case явным образом исключает непроизвольные ошибки программирования, допускающие переход одной ветви case в другую.
Несмотря на то что правило недопущения "провалов" не допускает переход одной ветви case в другую, в двух или более ветвях case все же разрешается ссылаться с помощью меток на одну и ту же кодовую последовательность, как показано в следующем примере программы.
<b>// Пример "проваливания" пустых ветвей case.</b>
<b>using System;</b>
<b>class EmptyCasesCanFall { </b>
<b> static void Main() { </b>
<b> int i;</b>
<b> for(i=1; i < 5; i++) </b>
<b> switch(i) {</b>
<b> case 1: </b>
<b> case 2:</b>
<b> case 3: </b>
<b> Console.WriteLine("i равно 1, 2 или 3<sup>"</sup>); </b>
<b> break;</b>
<b> case 4: </b>
<b> Console.WriteLine("i равно 4"); </b>
<b> break;</b>
<b> }</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы.
<b>i равно 1, 2 или 3</b>
<b>i равно 1, 2 или 3</b>
<b>i равно 1, 2 или 3</b>
<b>i равно 4</b>
Если значение переменной i в данном примере равно 1, 2 или 3, то выполняется первый оператор, содержащий вызов метода WriteLine(). Такое расположение нескольких меток ветвей case подряд не нарушает правило недопущения "провалов"; поскольку во всех этих ветвях используется одна и та же последовательность операторов.
Расположение нескольких меток ветвей case подряд зачастую применяется в том случае, если у нескольких ветвей имеется общий код. Благодаря этому исключается излишнее дублирование кодовых последовательностей.
Один оператор switch может быть частью последовательности операторов другого, внешнего оператора switch. И такой оператор switch называется вложенным. Константы выбора внутреннего и внешнего операторов switch могут содержать общие значения, не вызывая никаких конфликтов. Например, следующий фрагмент кода является вполне допустимым.
<b>switch(ch1) {</b>
<b>case 'A': </b>