355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Герберт Шилдт » C# 4.0: полное руководство » Текст книги (страница 7)
C# 4.0: полное руководство
  • Текст добавлен: 6 апреля 2017, 04:00

Текст книги "C# 4.0: полное руководство"


Автор книги: Герберт Шилдт



сообщить о нарушении

Текущая страница: 7 (всего у книги 83 страниц)

ГЛАВА 4 Операторы

В языке C# предусмотрен обширный ряд операторов, предоставляющих программирующему возможность полного контроля над построением и вычислением выражений. Большинство операторов в C# относится к следующим категориям: арифметические, поразрядные, логические и операторы отношения. Все перечисленные категории операторов рассматриваются в этой главе. Кроме того, в C# предусмотрен ряд других операторов для_ особых случаев, включая индексирование массивов, доступ к членам класса и обработку лямбда-выражений. Эти специальные операторы рассматриваются далее в книге вместе с теми средствами, в которых они применяются.


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

Арифметические операторы, представленные в языке С#, приведены ниже.

Оператор   Действие

+          Сложение

–           Вычитание, унарный минус

*          Умножение

/          Деление

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

–          Декремент

++         Инкремент

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

Действие арифметических операторов не требует особых пояснений, за исключением следующих особых случаев. Прежде всего, не следует забывать, что когда оператор / применяется к целому числу, то любой остаток от деления отбрасывается; например, результат целочисленного деления 10/3 будет равен 3. Остаток от этого деления можно получить с помощью оператора деления по модулю (%), который иначе называется оператором вычисления остатка. Он дает остаток от целочисленного деления. Например, 10 % 3 равно 1. В C# оператор % можно применять как к целочисленным типам данных, так и к типам с плавающей точкой. Поэтому 10.0 % 3.0 также равно 1. В этом отношении C# отличается от языков С и C++, где операции деления по модулю разрешаются только для целочисленных типов данных. В приведенном ниже примере программы демонстрируется применение оператора деления по модулю.

// Продемонстрировать применение оператора %.

using System;

class ModDemo {

  static void Main() {

    int iresult, irem;

    double dresult, drem;

    iresult = 10 / 3;

    irem = 10 % 3;

    dresult = 10.0 / 3.0;

    drem = 10.0 % 3.0;

    Console.WriteLine("Результат и остаток от деления 10/3: "

           + iresult + " " + irem);

    Console.WriteLine("Результат и остаток от деления 10.0 / 3.0: "

           + dresult + " " + drem);

  }

}

Результат выполнения этой программы приведен ниже.

Результат и остаток от деления 10/3: 3 1

Результат и остаток от деления 10.0 / 3.0: 3.33333333333333 1

Как видите, обе операции, % целочисленного типа и с плавающей точкой, дают один и тот же остаток, равный 1.


Операторы инкремента и декремента

Операторы инкремента (++) и декремента (—) были представлены в главе 2. Как станет ясно в дальнейшем, они обладают рядом особых и довольно интересных свойств. Но сначала выясним основное назначение этих операторов.

Оператор инкремента увеличивает свой операнд на 1, а оператор декремента уменьшает операнд на 1. Следовательно, оператор

х+ + ;

равнозначен оператору х = х + 1; а оператор

х–;

равносилен оператору

х = х – 1;

Следует, однако, иметь в виду, что в инкрементной или декрементной форме значение переменной х вычисляется только один, а не два раза. В некоторых случаях это позволяет повысить эффективность выполнения программы.

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

х = х + 1;

может быть записан в следующем виде:

++х; // префиксная форма

или же в таком виде:

х++; // постфиксная форма

В приведенном выше примере форма инкремента (префиксная или постфиксная) особого значения не имеет. Но если оператор инкремента или декремента используется в длинном выражении, то отличие в форме его записи уже имеет значение. Когда оператор инкремента или декремента предшествует своему операнду, то результатом операции становится значение операнда после инкремента или декремента. А когда оператор инкремента или декремента следует после своего операнда, то результатом операции становится значение операнда до инкремента или декремента. Рассмотрим следующий фрагмент кода.

х = 10;

у = ++х;

В данном случае значение переменной у будет установлено равным 11, поскольку значение переменной х сначала увеличивается на 1, а затем присваивается переменной у. Но во фрагменте кода

х = 10;

у = х++;

значение переменной у будет установлено равным 10, так как в этом случае значение переменной х сначала присваивается переменной у, а затем увеличивается на 1. В обоих случаях значение переменной х оказывается равным 11. Отличие состоит лишь том, когда именно это значение станет равным 11: до или после его присваивания переменной у.

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

// Продемонстрировать отличие между префиксной

// и постфиксной формами оператора инкремента (++).

using System;

class PrePostDemo {

  static void Main() {

    int x, y;

    int i;

    x = 1;

    y = 0;

    Console.WriteLine("Ряд чисел, полученных " +

              «с помощью оператора у = у + х++;»);

    for(i = 0; i < 10; i++)    {

      y = y + x++;    // постфиксная форма оператора ++

      Console.WriteLine(y + " ");

    }

    Console.WriteLine();

    x = 1;

    y = 0;

    Console.WriteLine("Ряд чисел, полученных    " +

              «с помощью оператора у = у + ++х;»);

    for(i = 0; i < 10; i++)    {

      y = y + ++x;    // префиксная форма оператора ++

      Console.WriteLine(y + " ");

    }

    Console.WriteLine();

  }

}

Выполнение этой программы дает следующий результат.

Ряд чисел, полученных с помощью оператора у = у + х++

1

3

б

10

15

14

21

28

36

45

55

Ряд чисел, полученных с помощью оператора у = у + ++х;

2

5

9

14

20

27

35

44

54

65

Как подтверждает приведенный выше результат, в операторе

у = у + х++;

первоначальное значение переменной х складывается с самим собрй, а полученный результат присваивается переменной у. После этого значение переменной х увеличивается на 1. Но в операторе

у = у + ++;

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

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

у + ++х;

Такое расположение рядом двух операторов может показаться не совсем привычным, но компилятор воспримет их в правильной последовательности. Нужно лишь запомнить, что в данном выражении значение переменной у складывается с увеличенным на 1 значением переменной х.


Операторы отношения и логические операторы

В обозначениях оператор отношения и логический оператор термин отношения означает взаимосвязь, которая может существовать между двумя значениями, а термин логический — взаимосвязь между логическими значениями "истина7' и «ложь». И поскольку операторы отношения дают истинные или ложные результаты, то они нередко применяются вместе с логическими операторами. Именно по этой причине они и рассматриваются совместно в данном разделе.

Ниже перечислены операторы отношения.

Оператор    Значение

==           Равно

!=          Не равно

>           Больше

<           Меньше

>=          Больше или равно

<=          Меньше или равно

К числу логических относятся операторы, приведенные ниже.

Оператор    Значение

&            И

|           ИЛИ

^           Исключающее ИЛИ

&&          Укороченное И

||          Укороченное ИЛИ

!           НЕ

Результатом выполнения оператора отношения или логического оператора является логическое значение типа bool.

В целом, объекты можно сравнивать на равенство или неравенство, используя операторы отношения == и ! =. А операторы сравнения <, >, <= или >= могут применяться только к тем типам данных, которые поддерживают отношение порядка. Следовательно, операторы отношения можно применять ко всем числовым типам данных. Но значения типа bool могут сравниваться только на равенство или неравенство, поскольку истинные (true) и ложные (false) значения не упорядочиваются. Например, сравнение true > false в C# не имеет смысла.

Операнды логических операторов должны относиться к типу bool, а результат выполнения логической операции также относится к типу bool. Логические операторы &, |, л и ! поддерживают основные логические операции И, ИЛИ, исключающее ИЛИ и НЕ в соответствии с приведенной ниже таблицей истинности.

p     q     p & q  p | q  ^ !p

false false false  false  false  true

true  false false  true   true    false

false true  false  true   true   true

true   true  true   true   false  false

Как следует из приведенной выше таблицы, результатом выполнения логической операции исключающее ИЛИ будет истинное значение (true), если один и только один ее операнд имеет значение true.

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

// Продемонстрировать применение операторов

// отношения и логических операторов.

using System;

class RelLogOps {

  static void Main() {

    int i, j;

    bool b1, 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(«Нельзя выполнить»);

    if(i >= j) Console.WriteLine(«Нельзя выполнить»);

    if(i > j) Console.WriteLine(«Нельзя выполнить»);

    b1 = true;

    b2 = false;

    if(b1 & b2) Console.WriteLine(«Нельзя выполнить»);

    if(!(b1 & b2)) Console.WriteLine(«!(b1 & b2) – true»);

    if(b1 | b2) Console.WriteLine(«bl I b2 – true»);

    if(b1 ^ b2) Console.WriteLine("bl ^ b2 – true");

  }

}

Выполнение этой программы дает следующий результат.

i < j

i <= j

i != j

!(b1 & b2) – true 

b1 | b2 – true

b1 A b2 – true

Логические операторы в C# выполняют наиболее распространенные логические операции. Тем не менее существует ряд операций, выполняемых по правилам формальной логики. Эти логические операции могут быть построены с помощью логических операторов, поддерживаемых в С#. Следовательно, в С# предусмотрен такой набор логических операторов, которого достаточно для построения практически любой логической операции, в том числе импликации. Импликация — это двоичная операция, результатом которой является ложное значение только в том случае, если левый ее операнд имеет истинное значение, а правый – ложное. (Операция импликации отражает следующий принцип: истина не может подразумевать ложь.) Ниже приведена таблица истинности для операции импликации.

p       q       Результат импликации p и q

true    true    true

true     false    false

false   false    true

false   true    true

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

! р I q

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

// Построение операции импликации в С#.

using System;

class Implication {

  static void Main() {

    bool p=false, q=false;

    int i, j;

    for(i =0; i < 2; i++) {

      for(j = 0; j < 2; j++) {

        if(i==0) = true;

        if(i==1) p = false;

        if(j==0) q = true;

        if(j==1) q = false;

          Console.WriteLine("p равно " + p + ", q равно " + q);

        if ( !p | q)

          Console.WriteLine("Результат импликации " + p +

                " и " + q + " равен " + true);

        Console.WriteLine();

      }

    }

  }

}

Результат выполнения этой программы выглядит так.

p равно True, q равно True

Результат импликации True и True равен True

p равно True, q равно False

p равно False, q равно True

Результат импликации False и True равен True

p равно False, q равно False

Результат импликации False и False равен True


Укороченные логические операторы

В C# предусмотрены также специальные, укороченные, варианты логических операторов И и ИЛИ, предназначенные для получения более эффективного кода. Поясним это на следующих примерах логических операций. Если первый операнд логической операции И имеет ложное значение (false), то ее результат будет иметь ложное значение независимо от значения второго операнда. Если же первый операнд логической операции ИЛИ имеет истинное значение (true), то ее результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода.

Укороченная логическая операция И выполняется с помощью оператора &&, а укороченная логическая операция ИЛИ – с помощью оператора | |. Этим укороченным логическим операторам соответствуют обычные логические операторы & и |. Единственное отличие укороченного логического оператора от обычного заключается в том, что второй его операнд вычисляется только по мере необходимости. -

В приведенном ниже примере программы демонстрируется применение укороченного логического оператора И. В этой программе с помощью операции деления по модулю определяется следующее: делится ли значение переменной d на значение переменной п нацело. Если остаток от деления n/d равен нулю, то п делится на d нацело.

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


// Продемонстрировать применение укороченных логических операторов.

using System;

class SCops {

  static void Main() {

    int n, d;

    n = 10;

    d = 2;

    if(d != 0 && (n % d) == 0)

      Console.WriteLine(n + " делится нацело на " + d);

    d = 0; // задать нулевое значение переменной d

    // d равно нулю, поэтому второй операнд не вычисляется

    if(d != 0 && (n % d) == 0)

      Console.WriteLine(n + " делится нацело на " + d);

    // Если теперь попытаться сделать то же самое без укороченного

    // логического оператора, то возникнет ошибка из-за деления на нуль,

    if(d != 0 & (n % d) == 0)

      Console.WriteLine(n + " делится нацело на " + d);

  }

}

Для исключения ошибки из-за деления на нуль в операторе if сначала проверяется условие: равно ли нулю значение переменной d. Если оно равно нулю, то на этом выполнение укороченного логического оператора И завершается, а последующая операция деления по модулю не выполняется. Так, при первой проверке значение переменной d оказывается равным 2, поэтому выполняется операция деления по модулю. А при второй проверке это значение оказывается равным нулю, следовательно, операция деления по модулю пропускается, чтобы исключить деление на нуль. И наконец, выполняется обычный логический оператор И, когда вычисляются оба операнда. Если при этом происходит деление на нуль, то возникает ошибка при выполнении.

Укороченные логические операторы иногда оказываются более эффективными, чем их обычные аналоги. Так зачем же нужны обычные логические операторы И и ИЛИ? Дело в том, что в некоторых случаях требуется вычислять оба операнда логической операции И либо ИЛИ из-за возникающих побочных эффектов. Рассмотрим следующий пример программы.

// Продемонстрировать значение побочных эффектов.

using System;

class SideEffects {

  static void Main() {

    int i;

    bool someCondition = false;

    i = 0;

    // Значение переменной i инкрементируется,

    // несмотря на то, что оператор if не выполняется,

    if(someCondition & (++i < 100))

      Console.WriteLine(«Не выводится»);

    Console.WriteLine("Оператор if выполняется: " + i); // выводится 1

    // В данном случае значение переменной i не инкрементируется,

    // поскольку инкремент в укороченном логическом операторе опускается,

    if(someCondition && ( ++i < 100))

      Console.WriteLine(«Не выводится»);

    Console.WriteLine("Оператор if выполняется: " + i); // по-прежнему 1 !!

  }

}

Прежде всего обратим внимание на то, что переменная someCondition типа bool инициализируется значением false. Далее проанализируем каждый оператор if. Как следует из комментариев к данной программе, в первом операторе if переменная i инкрементируется, несмотря на то что значение переменной someCondition равно false. Когда применяется логический оператор &, как это имеет место в первом операторе if, выражение в правой части этого оператора вычисляется независимо от значения выражения в его левой части. А во втором операторе if применяется укороченный логический оператор. В этом случае значение переменной i не инкрементируется, поскольку левый операнд (переменная someCondition) имеет значение false, следовательно, выражение в правой части данного оператора пропускается. Из этого следует вывод: если в коде предполагается вычисление правого операнда логической операции И либо ИЛИ, то необходимо пользоваться неукороченными формами логических операций, доступных в С#.

И последнее замечание: укороченный оператор И называется также условным логическим оператором И, а укороченный оператор ИЛИ – условным логическим оператором ИЛИ.


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

Оператор присваивания обозначается одиночным знаком равенства (=). В C# оператор присваивания действует таким же образом, как и в других языках программирования. Ниже приведена его общая форма.

имя_переменной = выражение

Здесь имя_переменной должно быть совместимо с типом выражения.

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

int х, у, z;

х = у = z = 100; // присвоить значение 100 переменным х, у и z

В приведенном выше фрагменте кода одно и то же значение 100 задается для переменных х, у и z с помощью единственного оператора присваивания. Это значение присваивается сначала переменной z, затем переменной у и, наконец, переменной х. Такой способ присваивания «по цепочке» удобен для задания общего значения целой группе переменных.


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

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

X = X + 10;

можно переписать, используя следующий составной оператор присваивания.

X += 10;

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

Рассмотрим еще один пример. Оператор

х = х – 100;

и оператор

X -= 100;

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

Для многих двоичных операций, т.е. операций, требующих наличия двух операндов, существуют отдельные составные операторы присваивания. Общая форма всех этих операторов имеет следующий вид:

имя_переменной ор = выражение

где ор – арифметический или логический оператор, применяемый вместе с оператором присваивания.

Ниже перечислены составные операторы присваивания для арифметических и логических операций.

+=

-=

*=

/=

%=

&=

|=

^=

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

У составных операторов присваивания имеются два главных преимущества. Во-первых, они более компактны, чем их "несокращенные" эквиваленты. И во-вторых, они дают более эффективный исполняемый код, поскольку левый операнд этих операторов вычисляется только один раз. Именно по этим причинам составные операторы присваивания чаще всего применяются в программах, профессионально написанных на С#.


    Ваша оценка произведения:

Популярные книги за неделю