Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Операторы, вычисление значения и приоритет операторов

Поиск

Операторы, вычисление значения и приоритет оператора

 

Понятие «Оператор»

 

В C# оператор — это элемент программы, который применяется к одному или нескольким операндам в выражении или операторе. Операторы, получающие на вход один операнд, например оператор инкремента (++) или new, называются унарными операторами. Операторы, получающие на вход два операнда, например, арифметические операторы (+, -, *, /) называются бинарными. Один оператор — условный оператор (?:) получает на вход три операнда и является единственным троичным оператором в C#.

Следующая строка кода C# содержит один унарный оператор и один операнд. Оператор инкремента ++ изменяет значение операнда y.

 

y++;

 

Следующая строка кода C# содержит два бинарных оператора, каждый с двумя операндами. Оператор присвоения = в качестве операндов принимает целочисленную переменную y и выражение 2 + 3. Выражение 2 + 3 само состоит из оператора сложения и два операнда, 2 и 3:

 

y = 2 + 3;

 

Операторы, вычисление значения и приоритет операторов

 

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

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

 

n1 = 11 - 2 * 4;

 

Умножение выполняется в первую очередь, так как умножение имеет приоритет над вычитанием.

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

 

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

 

Выражение Описание
x.y Доступ к членам
f(x) Вызов метода и делегата
a[x] Доступ к массиву и индексатору
x++ Постфиксное приращение
x-- Постфиксное уменьшение
new T(...) Создание объекта и делегата
new T(...){...} Создание объекта с инициализатором
new {...} Анонимный инициализатор объекта
new T[...] Создание массива
typeof(T) Получение объекта System.Type для T
checked(x) Вычисление выражения в проверенном контексте
unchecked(x) Вычисление выражения в непроверенном контексте
default (T) Получение значения по умолчания для типа T
delegate {} Анонимная функция (анонимный метод)

 

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

 

Выражение Описание
+x Удостоверение
-x Отрицание
!x Логическое отрицание
~x Поразрядное отрицание
++x Префиксное приращение
--x Префиксное уменьшение
(T)x Явное преобразование x в тип T

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

 

Выражение Описание
* Умножение
/ Деление
% Остаток

Аддитивные операторы

 

Выражение Описание
x + y Сложение, объединение строк, объединение делегатов
x - y Вычитание, удаление делегатов

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

 

Выражение Описание
x << y Сдвиг влево
x >> y Сдвиг вправо

Операторы отношения и типа

 

Выражение Описание
x < y Меньше
x > y Больше
x <= y Меньше или равно
x >= y Больше или равно
x is T Возвращает значение true, еслиx относится к типу T, в противном случае возвращает значение false
x as T Возвращает xтипа T или нулевое значение, если x не относится к типу T

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

 

Выражение Описание
x == y Равно
x!= y Не равно

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

 

Категория Выражение Описание
Логическое И x & y Целочисленное поразрядное AND, логическое AND
Логическое исключающее XOR x ^ y Целочисленное поразрядное исключающее XOR, логическое исключающее XOR
Логическое ИЛИ x | y Целочисленное поразрядное OR, логическое OR
Условное AND x && y Вычисляет y только если x имеет значение true
Условное OR x || y Вычисляет y только если x имеет значение false
Объединение нулей x?? y Равно y, если x — нулевое, в противном случае равно x
Условная x?: y: z Равно y, если x имеет значение true, z если x имеет значение false

Операторы назначения и анонимные операторы

 

Выражение Описание
= Присваивание
x op= y Составное присваивание. Поддерживает следующие операторы: +=, -=,*=,/=,%=, &=, |=,!=,<<=,>>=
(T x) => y Анонимная функция (лямбда-выражение)

Ассоциативность

 

Когда выражение содержит два или более операторов с одинаковым порядком применения, они вычисляются на основе ассоциативности. Запросы с левой ассоциативностью вычисляются слева направо. Например, x * y / z вычисляется как (x * y) / z. Запросы с правой ассоциативностью вычисляются справа налево. Например, оператор присваивания является право ассоциативным. Если бы это было не так, следующий код вызвал бы ошибку:

 

int a, b, c;

c = 1;

// Эквиваленты строчки ниже

a = b = c;

a = (b = c);

// Ошибка

//(a = b) = c;

 

Операторы присваивания и троичный оператор (?:) имеют правую ассоциативность. Все прочие двоичные операторы имеют левую ассоциативность.

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

 

Оператор Порядок вычислений
a = b a, b, =
a = b + c a, b, c, +, =
a = b + c * d a, b, c, d, *, +, =
a = b * c + d a, b, c, *, d, +, =
a = b - c + d a, b, c, -, d, +, =
a += b -= c a, b, c, -=, +=

13. Добавление скобок

 

Можно изменить порядок, установленный приоритетом и ассоциативностью операторов, воспользовавшись скобками. Например, выражение 2 + 3 * 2 в обычном случае будет иметь значение 8, поскольку операторы умножения выполняются раньше операторов сложения. Однако если выражение записано в форме (2 + 3) * 2, сложение выполняется перед умножением и в результате получается 10.Следующие примеры иллюстрируют порядок оценки выражений в скобках. Как и в предыдущих примерах, операнды вычисляются до того, как применяется оператор:

 

Оператор Порядок вычислений
a = (b + c) * d a, b, c, +, d, *, =
a = b - (c + d) a, b, c, d, +, -, =
a = (b + c) * (d - e) a, b, c, +, d, e, -, *, =

Перегрузка операторов

 

Поведение операторов для пользовательских классов и структур можно изменить. Такой процесс называется перегрузкой операторов.

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

 

Операторы Возможность перегрузки
+, -,!, ~, ++, --, true, false Эти унарные операторы можно перегрузить
+, -, *, /, %, &, |, ^, <<, >> Эти бинарные операторы нельзя перегрузить
==,!=, <, >, <=, >= Операторы сравнения можно перегрузить
&&, || Условные логические операторы нельзя перегрузить, но они вычисляются с помощью операторов & и |, допускающих перегрузку
[] Оператор индексирования массива нельзя перегрузить, но можно определить индексаторы
() Оператор приведения нельзя перегрузить, но можно определить новые операторы преобразования (explicit и implicit)
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= Операторы присвоения нельзя перегрузить, но, например, += вычисляется с помощью +, допускающего перегрузку.
=,.,?:, ->, new, is, sizeof, typeof Эти операторы нельзя перегрузить

 

Операторы сравнения можно перегружать, но только парами: если перегружен оператор ==, то != также должен быть перегружен. Обратный принцип также действителен и действует для операторов < и >, а также для <= и >=.

Для перегрузки оператора в пользовательском классе нужно создать метод в классе с правильной сигнатурой. Метод нужно назвать «operator X», где Xимя или символ перегружаемого оператора. Унарные операторы имеют один параметр, а бинарные — два. В каждом случае один параметр должен быть такого же типа, как класс или структура, объявившие оператор, как показано в следующем примере:

 

public static Complex operator +(Complex c1, Complex c2)

 

15. Операторы преобразования

 

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

 

class SampleClass

{

public static explicit operator SampleClass(int i)

{

SampleClass temp = new SampleClass();

// Код для преобразования из int в SampleClass...

return temp;

}

}

 

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

  • Преобразования, определенные как implicit, выполняются автоматически, если это требуется.
  • Для выполнения преобразований, определенных как explicit, требуется вызов операции приведения.
  • Все преобразования должны быть объявлены как static.

 

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

 

В этом примере используется оператор явного преобразования. Этот оператор преобразует тип значения Byte в тип значения Digit. Поскольку в тип Digit могут быть преобразованы не все значения типа Byte, преобразование выполняется явным образом, что означает использование операции приведения, как показано в методе Main:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LC_Console

{

struct Digit

{

byte value;

 

public Digit(byte value) // Конструктор

{

if (value > 9)

{

throw new System.ArgumentException();

}

this.value = value;

}

 

public static explicit operator Digit(Byte b) // Явное преобразование Byte в Digit

{

Digit d = new Digit(b); // Преобразование

 

Console.WriteLine("Преобразование прошло");

Console.WriteLine("Для продолжение нажмите любую клавишу... ");

Console.ReadKey();

return d;

}

}

 

class TestExplicitConversion

{

static void Main()

{

 

try

{

byte b = 3;

Digit d = (Digit)b; // Преобразование

}

catch (System.Exception e)

{

Console.WriteLine("Поймали исключение: {0}", e);

}

}

}

}

/* Выведет:

* Преобразование прошло

* Для продолжение нажмите любую клавишу...

*/

 

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

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LC_Console

{

struct Digit

{

byte value;

 

public Digit(Byte value)

{

if (value > 9)

{

throw new System.ArgumentException();

}

this.value = value;

}

 

public static implicit operator byte(Digit d) // Неявное преобразование Digit в Byte

{

Console.WriteLine("Преобразование прошло");

Console.WriteLine("Для продолжение нажмите любую клавишу... ");

Console.ReadKey();

return d.value; // Неявное преобразование

}

}

 

class TestImplicitConversion

{

static void Main()

{

Digit d = new Digit(3);

byte b = d; // Неявное преобразование

}

}

}

/* Выведет:

* Преобразование прошло

* Для продолжение нажмите любую клавишу...

*/



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 513; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.139.72.210 (0.007 с.)