Г. Шилдт - Полный справочник по C# (1160789), страница 18
Текст из файла (страница 18)
Но инструкция1 у = х + ++х;выполняется по-другому. Сначала она получает (и запоминает) исходное значение переменной х, затем инкрементирует его, суммирует новое значение с исходным, а результат суммирования присваивает переменной у.
Нетрудно заметить, что простая замена элемента х++ элементом ++х меняет числовой ряд, генерируемый программой, счетного на нечетный.И еще. Выражение1 х + ++х;на первый взгляд может показаться странным, но только не компилятору. Несмотряна стоящие рядом два оператора, компилятор позаботится о правильной последовательности их выполнения. Достаточно понимать, что в этом выражении значение переменной х суммируется с инкрементированным значением той же переменной х.—I Операторы отношений и логические операторыОператоры отношений оценивают по "двубальной системе" (ИСТИНА/ЛОЖЬ)отношения между двумя значениями, а логические определяют различные способысочетания истинных и ложных значений.
Поскольку операторы отношений генерируют ИСТИНА/ЛОЖЬ-результаты, то они часто выполняются с логическими операторами. Поэтому мы и рассматриваем их в одном разделе.Итак, перечислим операторы отношений.Оператор==1=><>=<=84ЗначениеРавноНе равноБольшеМеньшеБольше или равноМеньше или равноЧасть I.
Язык С#Приведем список логических операторов.ОператорЗначениеИИЛИИсключающее ИЛИСокращенное ИСокращенное ИЛИНЕРезультат выполнения операторов отношений и логических операторов имеет типbool.В С# на равенство или неравенство можно сравнивать (соответственно, с помощью операторов == и !=) все объекты. Но такие операторы сравнения, как <, >, <=или >=, можно применять только к типам, которые поддерживают отношения упорядочения. Это значит, что все операторы отношений можно применять ко всем числовым типам.
Однако значения типа bool можно сравнивать только на равенство илинеравенство, поскольку значения t r u e и f a l s e не упорядочиваются. Например, в С#сравнение t r u e > f a l s e не имеет смысла.Что касается логических операторов, то их операнды должны иметь тип bool, ирезультат логической операции всегда будет иметь тип bool. Логические операторы &,|, А и ! выполняют базовые логические операции И, ИЛИ, исключающее ИЛИ и НЕв соответствии со следующей таблицей истинности.рЯp & qP 1 ЯPfalsefalsefalsefalsefalsetruetruefalsefalsetruetruefalsefalsetruefalsetruetruetruetruetruefalsefalsetruetrueлЯIPКак видно из этой таблицы, операция "исключающее ИЛИ" сгенерирует результатИСТИНА лишь в случае, если истинен только один из ее операндов.Рассмотрим программу, которая демонстрирует использование операторов отношений совместно с логическими операторами.// Демонстрация использования операторов отношений/ / и логических операторов.using System;class RelLogOps {public s t a t i c void Main() {int i , j ;bool bl, b2;/-i = 10;j = 11;if(i < j) Console.WriteLine ("i < j");if(i <= j) Console.WriteLine("i <= j");if(i != j) Console.WriteLine ("i != j");if(i == j) Console.WriteLine("Это не будет выполнено.");Глава 4.
Операторы85if(iif(i>= j) Console.WriteLine("Это не будет выполнено.");> j) Console.WriteLine("Это не будет выполнено.");bl = t r u e ;Ь2 = f a l s e ;i f ( b l & Ь2) Console.WriteLine("Это не будет выполнено.")i f ( ! ( b l & Ь2)) Console.WriteLine("!(bl& Ь2) — ИСТИНА")i f ( b l t Ь2) Console.WriteLine("bl| Ь2 ~ ИСТИНА");i f ( b l А Ь2) Console.WriteLine("bl A Ь2 - - ИСТИНА");Результат выполнения этой программы таков:1<=i!=j! (bl & b 2 ) — ИСТИНАb l I b 2 - - ИСТИНАb l A b2 — ИСТИНАРассмотренные выше логические операторы предназначены для выполнения самых распространенных логических операций. Однако существует ряд других операций, которые определяются правилами формальной логики.
Их также можно выполнить с помощью логических операторов С#. Так, С# поддерживает набор логическихоператоров, на базе которых можно построить любую другую логическую операцию,например операцию импликации. Импликация — это логическая операция, результаткоторой будет ложным только в случае, когда левый операнд имеет значениеИСТИНА, а правый — ЛОЖЬ. (Операция импликации отражает идею о том, что истина не может подразумевать ложь.) Вот как выглядит таблица истинности для оператора импликации:рqРезультат импликации р и qtruetruetruefalsetruefalsefalsefalsetruefalsetruetrueОперацию импликации можно создать, используя комбинацию операторов ! и | .!р I qИспользование импликации демонстрируется в следующей программе:// Создание оператора импликации в языке С#.using System;class Implication {public static void Main() {bool p=false, q=false;int i, j ;for(i = 0 ; i < 2; if o r ( j = 0; j < 2; 3++)if(i==0) P = true;i f ( i = = l ) P = false;if(j==0) q = true;i f ( j = = l ) q = false;86Часть I.
Язык С#Console.WriteLine("p равно " + p + ", q равно " + q ) ;if(!pI q)Console.WriteLine("Результат импликации " +p + " и " + q + " равен " + true);Console.WriteLine();Результат выполнения этой программы выглядит так:р равно True, q равно TrueРезультат импликации True и True равен Trueр равно True, q равно Falseр равно False, q равно TrueРезультат импликации False и True равен Trueр равно False, q равно FalseРезультат импликации False и False равен TrueСокращенные логические операторыС# поддерживает специальные сокращенные (short-circuit) версии логических операторов И и ИЛИ, которые можно использовать для создания более эффективногокода.
Вспомним, что, если в операции И один операнд имеет значение ЛОЖЬ, результат будет ложным независимо от того, какое значение имеет второй операнд. Аесли в операции ИЛИ один операнд имеет значение ИСТИНА, результат будет истинным независимо от того, какое значение имеет второй операнд. Таким образом, вэтих двух случаях вычислять второй операнд не имеет смысла. Если не вычисляетсяодин из операндов, тем самым экономится время и создается более эффективный код.Сокращенный оператор И обозначается символом &&, а сокращенный операторИЛИ — символом | | (их обычные версии обозначаются одинарными символами & иI, соответственно).
Единственное различие между обычной и сокращенной версиямиэтих операторов состоит в том, что при использовании обычной операции всегда вычисляются оба операнда, в случае же сокращенной версии второй операнд вычисляется только при необходимости.Рассмотрим программу, в которой демонстрируется использование сокращенногооператора И. Программа определяет, является ли значение переменной d множителемчисла п. Здесь используется операция деления по модулю. Если остаток от деленияd / n равен нулю, значит, d — множитель числа п. Чтобы не допустить ошибки деления на нуль, используется сокращенная форма оператора И.// Демонстрация использования сокращенных операторов.u s i n g System;class SCops {public static void Main() {int n, d;n = 10;d = 2;if(d != 0 && (n % d) == 0)Глава 4.
Операторы87Console.WriteLine(d + " -- множитель числа " + n ) ;d = 0; // Теперь установим d равным нулю.// Поскольку d равно нулю,// второй операнд не вычисляется.if(d != 0 && (п % d) == 0)Console.WriteLine(d + " -- множитель числа " + n ) ;/* Теперь попробуем проделать то же самое безсокращенного оператора. Такая попытка приведетк ошибке (деление на нуль).
*/if(d != 0 & (п % d) == 0)Console.WriteLine(d + " — множитель числа " + n ) ;Чтобы не допустить деления на нуль, в инструкции i f сначала проверяется значение переменной d на равенство нулю. Если наши опасения окажутся ненапрасными,выполнение сокращенного оператора И на этом прекратится. В первой проверке, когда переменная d содержит число 2, операция деления по модулю выполняется. Вторая проверка (а ей предшествует принудительная установка переменной d нулем) показывает, что второй операнд вычислять не имеет смысла, поэтому деление на нульопускается. Попытка заменить сокращенный оператор И обычным заставит вычислить оба оператора и, как следствие, приведет к ошибке деления на нуль.Поскольку сокращенные формы операторов И и ИЛИ в некоторых случаях работают эффективнее своих обычных "коллег", читатель мог бы задать вполне резонныйвопрос: "Почему бы компилятору С# вообще не отказаться от обычных форм этихоператоров?".
Дело в том, что иногда необходимо, чтобы вычислялись оба операнда,поскольку вас могут интересовать побочные эффекты вычислений. Чтобы прояснитьситуацию, рассмотрим следующую программу:// Демонстрация важности побочных эффектов.using System;class SideEffects {public static void Main() {int i ;i = 0;/* Здесь значение i инкрементируется, несмотря на то,что инструкция выполнена не будет.
*/if(false & (++i < 100))Console.WriteLine("Этот текст не будет выведен.");Console.WriteLine("Инструкция if выполнена: " + i ) ; // Отображает: 1/* В этом случае значение i не инкрементируется, посколькусокращенный оператор И опускает инкрементирование. */if(false && (++i < 100))Console.WriteLine("Этот текст не будет выведен.");Console.WriteLine("Инструкция if выполнена: " + i ) ; // По-прежнему 1 !!Часть I. Язык С #Как поясняется в комментариях, в первой if-инструкции значение переменной iинкрементируется независимо от результата выполнения самой if-инструкции. Нопри использовании сокращенной версии оператора И во второй if-инструкции значение переменной i не инкрементируется, поскольку первый операнд имеет значениеf a l s e . Из этого примера вы должны извлечь следующий урок.
Если в программе предполагается обязательное выполнение правого операнда операции И/ИЛИ, вы должныиспользовать полную, или обычную, форму этих операторов, а не сокращенную.И еще одна терминологическая деталь. Сокращенный оператор И также называется условным Я, а сокращенный ИЛИ — условным ИЛИ.Оператор присваиванияС оператором присваивания мы "шапочно" познакомились в главе 2. Теперь пришло время для более официального знакомства. Оператор присваивания обозначаетсяодинарным знаком равенства (=). Его роль в языке С# во многом такая же, как и вдругих языках программирования. Общая форма записи оператора присваивания имеет следующий вид.переменная= выражение;Здесь тип элемента переменная должен быть совместим с типом элемента выражение.Оператор присваивания интересен тем, что позволяет создавать целую цепочкуприсвоений.
Рассмотрим, например, следующий фрагмент кода.i n t х, у, z;х = у = z = 100;// Устанавливаем переменные х, у// и z равными 100.В этом фрагменте значения переменных х, у и z устанавливаются равными 100 в одной инструкции. Эта инструкция успешно работает благодаря тому, что оператор присваивания генерирует значение правостороннего выражения. Это значит, что значениевыражения z = 100 равно числу 100, которое затем присваивается переменной у, послечего в свою очередь присваивается переменной х. Использование цепочки присвоений — простой способ установить группу переменных равными одному (общему длявсех) значению.Составные операторы присваиванияВ С# предусмотрены специальные составные операторы присваивания, которыеупрощают программирование определенных инструкций присваивания. Лучше всегоначать с примера.