Главная » C# » Операторы Visual C# (Sharp)

0

На  протяжении  всей  этой  книги  мы  видели  применение  различных  операторов в  примерах,  таких  как оператор  присваивания  (а=3;) или  логические  операторы (i f (a==b)). В С# имеются многие другие арифметические операторы, которые можно использовать для обработки типов. Кроме этого, можно также определять пользовательские операторы.

Арифметические операторы

Операторы вычитания (-), умножения (*) и деления (/ ) обычно применимы только с числовыми значениями. Эти операторы прямым образом соответствуют матемическим операторам, которые мы изучаем в начальной школе. Теперь рассмотрим, что могут делать другие арифметические операторы.

Сложение

Оператор сложения (+) применяется для указания сложения двух значений:

Операция сложения состоит из правой и левой частей, разделенных знаком раветва (=). В правой части переменная с складывается со значением 1 и присваиваея переменной а.

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

а =  а  +  1;

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

Вот еще один пример последовательного вычисления: b =  а  =  а  +  1;

В этом примере, значение переменной ь равно значению переменной а, которое равно значению переменной а, сложенному со значением 1.

Знак сложение не означает сложение для всех типов. В случае  строковых типов, знак "плюс" выполняет операцию конкатенации:

string а = b + с;

Побитовые операторы

Результатом применения унарного оператора побитового отрицания (~) является обратное число. Этой операции необходимо уделить особое внимание, т. к. резулат не всегда очевиден. Рассмотрим следующий пример:

а  =  ~8;

Результатом этой операции будет -9 . Такой результат дает повод предполагать, что алгоритм для определения обратного числа добавляет к исходному числу 1 и мент знак на обратный. Такой подход может и работать на практике, но это не совсем точное описание происходящего. В действительности, обратное число вычисляется по двоичным битам. В двоичном представлении число 8 выглядит таким образом:

1000

Если бы число 8 было типа short, то его представление было бы следующим: 0000000000001000

Обращение каждого бита дает следующее значение:

1111111111110111

Так как это значение типа short, то первый бит указывает знак числа, а остальные представляют само число, таким образом, получая -9 .

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

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

class PersonWithAttributes { public bool IsPersonTall; public bool WearsHats; public bool RunsSlowly;

}

В данном определении класса PersonWithAttributes каждый атрибут представлен членом данных. Другим способом получить этот же результат будет рассмотрение кдого атрибута, как двоичного флага, закодированного в класс PersonWithAttributes:

class PersonWithAttributes { public int Attributes;

}

В модифицированном  коде класса булевы атрибуты закодированы  в член данных

Attributes в виде битовых флагов.

Кодирование атрибута в виде флага просто означает присвоение соответствующу биту числа соответствующего значения. Для доступа к отдельным битам нужно создать константы, являющиеся степенью числа 2. Таким образом, три  булевых члена данных преобразуются в следующие константы:

const int isTall = 1; const int wearsHats = 2; const int runsSlow = 4;

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

PersonWithAttributes person = new PersonWithAttributes(); person.Attributes = isTall | runsSlow;

Переменной person.Attributes присваиваются значения  isTall и runsSlow. Так как значение isTall равно 0001, a runsSlow— 0010, то результатом выполнения побитовой операции логического "ИЛИ" (| ) будет значение 0011.

Результатом побитовой операции "ИЛИ" над двумя битами будет единица, если любой из битов равен единице. В десятичном представлении результатом данного сравнения будет число 3. Но это число не имеет значения, т. к. мы выполняем питовые операции.

Проверить человека на высокий рост (isTall) можно следующим кодом:

if ((person.Attributes & isTall) != 0) {

Console.WriteLine)"Person is tall");

}

! 8 Зак. 555

else {

Console.WriteLine("Person is not tall");

}

Выделенный жирным шрифтом код выполняет операцию побитового "И" (&), в корой значение isTali сравнивается с соответствующим флагом в атрибутах челека. Результатом побитовой операции "И" над двумя битами будет единица, только если оба бита равны единице. В случае совпадений будет возвращено ненулевое значение. В данном  примере будет совпадение с isTali, т. к. эта характеристика была присвоена данному индивидууму.

Допустим, что мы применим побитовый оператор отрицания следующим образом:

person.Attributes = -person.Attributes;

Тогда,  в  результате  обращения  значений  битов  на  противоположные,  флаг  для

isTali станет равным нулю, а для wearsHat — единице.

При операции побитового сдвига биты сдвигаются слева направо или справа нало на количество указанных позиций. В следующем коде биты сдвигаются оперором «  на две позиции влево.

int shifted = 8; shifted = shifted « 2;

По исполнению кода значение переменной shifte d будет равняться 32. В двоиом представлении число 8 выглядит как 001000. Результатом смещения битов на две позиции влево будет двоичное значение 100000, что в  десятичном  формате равно 32.

А в следующем коде приводится пример побитового сдвига вправо:

int shifted = 8; shifted = shifted » 2;

В результате этой операции значение переменной shifte d станет равным двоичну 10 или десятичному 2.

В основном, скорее всего, у вас не будет надобности использовать операторы питового сдвига. Если только вы не занимаетесь программированием аппаратной части (например, взаимодействие с интерфейсом GUI), то все, для чего использтся флаги, можно реализовать с помощью булевых типов и типов struct. Но на случай, если вам придется столкнуться с побитовыми операторами, вы  будете знать, что они делают.

Деление по модулю

Оператор деления по модулю (%) очень полезен, когда необходимо знать остаток после выполнения операции деления. Например, результатом следующей операции деления будет значение 2.

int а = 12 / 5;

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

int remainder = 12 % 5;

Инкремент и декремент

Операторы инкремента  (++) и декремента  (– ) могут  быть более удобными, чем традиционные операторы сложения и вычитания. Но для их правильного примения необходимо понимать их очередность. Рассмотрим следующий код:

int а = 2;

а  ++;

По умолчанию, значение переменной а будет 3. А теперь, допустим, мы выполним следующий код:

class Program

{

static int Loop(int counter) { return (counter ++);

}

static void Main(string!] args)

{

int count = 0;

for (int cl = 0; cl < 10; cl ++) { count = Loop(count);

Console.WriteLine("Value (" + count + ")");

}

}

}

Может создаться впечатление, что, поскольку метод Loop увеличивает значение, то значение переменной count увеличивается. В действительности же полученный результат будет следующим:

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

Value (0)

То есть значение переменной count не увеличивается. Причина такого странного поведения идет из .истоков языка С, где очередность исполнения ключевого слова return была выше, чем оператора ++.

ПРИМЕЧАНИЕ

Язык программирования С был основан в 70-х годах прошлого  столетия.  В  настоящее время С обычно применяется только для написания драйверов и подобного рода прраммного  обеспечения.   Большинство  программистов  дл я  написания  своих  програм м не  использует С.

Чтобы программа работала должным образом, метод Loop нужно модифицировать, как показано в следующем коде:

static int Loop(int counter) { return (++counter);

}

Оператор инкремента был вынесен перед переменной identifier и поэтому волняется перед ключевым словом return.

Источник: Гросс  К. С# 2008:  Пер. с англ. — СПб.:  БХВ-Петербург, 2009. — 576 е.:  ил. — (Самоучитель)

По теме:

  • Комментарии