Суббота, 18.05.2024, 17:45
Приветствую Вас Гость | RSS
Форма входа
Поиск
Календарь
«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Charles Petzold ".NET Book Zero" Глава 7. Операторы и выражения

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

Operator Precedence and Associativity

Category

Operators

Associativity

Основные операторы

(x) x.y f(x) a[x] x++ x--
new typeof sizeof checked unchecked

Left to right

Унарные

+ – ! ~ ++x --x (T)x

Left to right

Мультипликативные

* / %

Left to right

Аддитивные

+ -

Left to right

Операторы сдвига

<< >>

Left to right

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

< > <= >= is as

Left to right

Операторы равенства

== !=

Left to right

Логическое – И (AND)

&

Left to right

Логическое –
исключающее ИЛИ (XOR)

^

Left to right

Логическое – ИЛИ (OR)

|

Left to right

Условное – И (AND)

&&

Left to right

Условное – ИЛИ (OR)

||

Left to right

Условие

?:

Right to left

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

= *= /= %= += -= <<= >>= &= ^= |= ??

Right to left

 

Ветераны C программирования признают в ней измененную версию таблицы, со стр 49 в первом издании Брайана Кернигана и Денниса Ритчи "Язык программирования C" (Prentice-Hall, 1978). C# версия таблицы содержится в §7.2.1 "C# Language Specification". Оператор – "запятая", существующий в С и C++, не поддерживается в C#.

При работе с C#, полезно думать в терминах операторов и выражений, вместо объявлений. Операторы, как правило, символы или небольшие слова, которые вызывают изменения переменных, или которые используют значения переменной или нескольких переменных для получения единого результата. Выражение включает в себя один или несколько операторов. Например:

A + B 

это выражение. Это не объявление, даже если вы поставите точку с запятой после этого. (C# не позволяет оператору сложения быть использованным самому по себе, как объявлению, поскольку объявление не делает ничего.) Приведенная выше таблица показывает, как компилятор C# оценивает сложные выражения. Например, если смешать мультипликативный оператор и аддитивный оператор в одном объявлении, мультипликативный оператор будет оцениваться в первую очередь. В объявлении

C = A + B * 5; 

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

C = A / B * 5; 

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

Если приоритет по умолчанию и ассоциированности не такой, какой вам необходим, вы можете использовать скобки, чтобы изменить его:

C = (A + B) * 5; 

Теперь, сложение происходит в первую очередь. Пара круглых скобок считается оператором, и он является первым оператором перечисленным в строке "Основных" операторов. Подход к C# с точки зрения выражений и операторов, будет полезен в понимании того, что здесь произойдёт:

Console.WriteLine(C = A + B); 

Некоторые языки не позволят вам так сделать, потому что, в них присваивание не считается оператором, как знак плюс. (Visual Basic .NET, например, будет интерпретировать знак "равно" как оператор эквивалентности). В C#, сложение оценивается в первую очередь. Как вы можете видеть в таблице, аддитивные операторы имеют более высокий приоритет, чем операторы присваивания. Результат операции сложения становится правой частью операции присваивания. Знак равенства устанавливает переменную слева – равной значению справа. Кроме того – и это очень важно в примере – операция присваивания имеет результат, и этот результат – новое значение переменной слева. Этот результат -значение, передаваемое в метод Console.WriteLine.

Основные операторы

Вы уже видели большинство операторов из первого ряда таблицы:

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

Оператор х.у символизирует период, который как вы видели разделяет пространства имён, имена классов и структур, а также методы, поля и имена свойств.

Оператор f(x) символизирует вызов метода (где "f" означает – "function", конечно же!).

Оператор a[x] символизирует доступ к массиву и индексу, например – к строковому массиву.

x++ и x-- операторы символизируют пост-инкремент и пост-декремент. Переменная увеличивается или уменьшается, но только после того, как переменная используется в выражении. Например:

int A = 55;
Console.WriteLine(A++);
Console.WriteLine(A); 

Первый Console.WriteLine отобразит 55, потому что это значение до приращения. Второй Console.WriteLine отобразит 56.

Вы уже видели оператор new, а также checked и unchecked. Мы будем обсуждать typeof в главе 19. Я не буду обсуждать sizeof в этой книге.

Унарные операторы

Эти операторы называются "унарными" потому что они имеют только один аргумент, который всегда находится в правой части оператора. Оператор "+" определен для всех числовых типов, но обычно ничего не делает. Например, выражение:

+A 

просто A. Однако, оператор может быть переопределен классом или структурой.

Результатом оператора "-" будет отрицательное число. (Оператор не меняет саму переменную). Оператор "!" логическое отрицание и определён только для bool. При применении к истинному значению, результат будет ложным, а при применении к ложному, результат будет истинным.

~ является оператором побитового дополнения и определена только для int, uint, long, и ulong. Результатом оператора будет целое число того же типа, в котором все биты были перевернуты – 0 на 1 и 1 на 0. Операторы пре-инкремента и пост-инкремента обозначаются ++х и --x. Переменная увеличивается или уменьшается, и это является результатом операции.

Оператор (T)х символизирует приведение типов. C# гораздо строже с приведением типов, чем C. Если вам нужно конвертировать из одного типа данных в другой сверх того, что позволяет C#, класс Convert (определенный в пространстве имен System) предоставляет множество методов, которые, вероятно, сделают то, что вы хотите.

Мультипликативные и арифметические операции

Мультипликативные и арифметические операторы определены для всех числовых типов данных. А оператор сложения, также определен и для строкового типа данных. В отличие от C и C++, оператор получения остатка определён только для float и double, как я уже говорил в предыдущей главе.

Операторы сдвига

Операции сдвига – сдвигают целое число (находящееся в левой части оператора) в соответствии с заданным количеством битов (операнд справа). "<<" – оператор сдвига влево; ">>" – оператор сдвига вправо. Операнд слева должен быть int, uint, long, и ulong. Операнд справа должен быть int. При смещении int или uint, используются только 5 битов операнда справа; при смещении long или ulong, используются только 6 битов правого операнда. Когда int или long сдвигается вправо, происходит арифметический сдвиг. То есть, освобожденные старшие биты помещаются в бит знака.

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

Четыре первых оператора сравнения, <, >, <= и >= определены для всех числовых типов и возвращают логическое значение.

Существует два оператора сравнения типов и они будет обсуждаться в главе 19.

Операторы равенства

Два оператора равенства == и != определены для всех числовых типов. Они возвращают логическое значение.

Есть некоторые особые факторы для операторов равенства, их я обсуждаю в главе 16. А пока, вы можете быть приятно удивлены тем, что операторы равенства могут работать со строковыми объектами. Две строки считаются равными, если они имеют одинаковую длину и соответствующие символы. Сравнение чувствительно к регистру. Другие типы сравнений можно осуществить с помощью методов, определенных в классе String.

Логические и условные операторы

Я хочу обсудить два оператора AND и OR более детально, потому что они могут вызвать некоторую путаницу среди C и C ++ программистов. "&", "^", и "|" операторы называют логическое AND, XOR и OR. (В C, они называются – битовые операторы.) В C# эти операторы определены для двух интегральных типов данных и bool. Для целочисленных типов данных, они функционируют как битовые операции, так же, как в C. Например, выражение:

0x03 | 0x05 

вычислится как 0x07.

Для типов данных bool, логические операторы возвращают результат типа bool. Результат логического оператора "AND" будет true, только если оба операнда будут true. Результат логической операции "XOR" будет – true только тогда, когда один из операндов true, а другое false. Результат логической операции "OR" – true, если один из операндов является истинным.

В C, "&&" и "||" операторы известны как логические операторы. В C#, они называются – условный AND и условный OR, и они определены только для типов данных bool.

С программисты привыкли к использованию && и || операторов в выражениях, таких как это:

A != 0 && B > 5 

C программисты также знают, что если первое выражение вычисляется как ложное (то есть, если равно 0), то второе выражение не вычисляется. Это важно знать, потому что, второе выражение может включать присваивание или вызов функции. Аналогичным образом, когда вы используете оператор ||, второе выражение не вычисляется, если первое выражение истинно. В C# вы используете && и || оператор таким же образом, как вы используете их в C. Эти операторы называются условными AND и OR потому, что второй операнд оценивается только в случае необходимости.

В C#, вы можете использовать & и | операторы таким же образом, как && и ||, как в этом примере:

A != 0 & B > 5 

При использовании в C# операторов & и | таким образом, оба выражения оцениваются независимо от результата первого выражения.

Выражения, использующие &, а не &&, конечно, разрешены в С, и они работают так же, как в C#, но большинство программистов C, скорее всего, напишут такое выражение только по ошибке. Выражение выглядит неверным для многих C программистов, потому что они научили себя относиться к &, как побитовому AND, и к && – как к логическому AND. Но в C результат реляционного или логического выражения является INT, которое имеет значение 1, если выражение истинно, и 0 в противном случае. Вот почему операция побитового AND здесь работает.

Программист может сделать первоначальное выражение с участием оператора && немного более кратким, написав его так:

A && B >= 5 

Это отлично работает в C, потому что C обрабатывает любое ненулевое выражение как true. В C#, однако, это выражение является запрещенным, поскольку оператор && определяется только для типов данных bool.

Вот где C программист получает в большие проблемы при использовании оператора побитового AND, выражение в кратком виде:

A & B >= 5 

Если B равно 7, то выражение в правой части оценивается как значение 1. Если равно 1 или 3 или любому нечетному числу, то побитовое AND принимает 1 и общее выражение оценивается как истинное. Если равно 0 или 2, или любому чётному числу, то битовое AND принимает 0 и суммарное выражение оценивается как ложное. Вполне вероятно, что ни один из этих результатов – совсем не то, что хотел программист, и именно поэтому программисты на С имеют такую болезненную реакцию видя побитовый AND или OR оператор в логических выражениях. (В C# такие выражения является запрещенными, поскольку целые числа и значения bool не могут быть смешаны в логических AND, XOR, или OR выражениях).

Предположим, у вас есть целая переменная называющаяся year, и вы хотите, вычислить логическое значение под именем isLeapYear. Високосный год, как правило, приходится на годы, делящиеся на 4, за исключением того, что год, делящийся на 100 – не високосный год, кроме случаев, когда год делится на 400. Вы можете сделать это следующим образом:

bool isLeapYear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);

Первое выражение должно интерпретироваться как:

year % 4 == 0 

Это выражение будет истинным только тогда, когда год без остатка будет делится на 4. Выражение

year & 3 == 0 

делает аналогичную работу. Одинарный амперсанд является побитовым AND в этом выражении, и результат равный 0 будет, только если год полностью делится на 4. В любом случае, три четверти всех значений исключены. Поскольку следующий оператор является условным, оставшаяся часть выражения даже не будет вычисляться для трех четвертей всех значений. Остальная часть выражения заключена в круглые скобки:

(year % 100 != 0 || year % 400 == 0) 

Это выражение вычисляется, только если год делится на 4. Оно предназначено для устранения значений, кратных 100, но не кратных 400. Это выражение является истинным, если год делится на 400, или если год не делится на 100.

Условный оператор

Условный оператор, который символизирован знаком "?:" в таблице, является тройным оператором, что означает, что он имеет три операнда:

A ? B : C 

Выражение А должно принимать значение bool. Результатом работы будет является B, если значение истинно, и C, если ложно.

Использование этого оператора обычно ограничено в особых случаях, в таких, как этот код, который добавляет "s" в какой-то текст, только если отображаемое значение не равно 1:

Console.WriteLine("Please deposit {0} dollar{1}.",
dollars, dollars == 1 ? '' : 's'); 

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

Присваивание это – бинарная операция, и результатом выражения присваивания является присваиваемое значение. Присваивания оценивается справа налево, делая возможным выражения, подобные этому:

A = B = 3; 

B присваивается значение 3, и оно также является результатом выражения присваивания. Этот результат затем присваивается А.

Как C и C++, C# также поддерживает популярные составные операторы присваивания для сложения, вычитания, умножения, деления, вычисления остатка, сдвига, и AND, OR, и XOR и в их побитовых и логических интерпретаций. Последний оператор перечислены в таблице – "??", называющийся нуль-коалесцентным оператором, я опишу в главе 27.


© Charles Petzold ".NET Book Zero" 2007