Шаг 105.
Язык программирования C#. Начала
Перегрузка операторов. Операторные методы

    На этом шаге мы приведем общие сведения о механизме перегрузки операторов.

    Как мы уже знаем, в языке C# есть много различных операторов, которые позволяют выполнять всевозможные операции со значениями разных типов. Например, мы можем с помощью оператора "плюс" + сложить два числа и получить в результате число. Мы можем "сложить" с помощью того же оператора два текстовых значения и получить в результате текст. Существуют и другие ситуации, когда мы можем использовать оператор + (или какой-нибудь иной оператор). Все они предопределены: то есть случаи, когда мы можем использовать тот или иной оператор, определены заранее и зависят от типа операндов, участвующих в операции. Другими словами, имеется ограниченное количество ситуаций, в которых могут использоваться операторы языка С#, а результат выполнения операций зависит от типа операндов. Например, мы можем к тексту прибавить число, но не можем текст умножить на число. В этом смысле наши возможности ограничены и строго детерминированы. Но есть в языке C# очень мощный и эффективный механизм, который связан с перегрузкой операторов. Основная идея в том, что для объектов пользовательских классов (то есть классов, которые мы описываем в программе) доопределяется действие встроенных операторов языка С#. Скажем, описывая класс, возможно путем несложных манипуляций добиться того, что объекты этого класса можно будет складывать, как числа. Или, например, к объекту класса можно будет прибавить число, и так далее. Смысл каждой такой операции определяем мы, когда описываем класс.

    Чтобы определить способ применения того или иного оператора к объектам класса, в классе описывается специальный метод, который называется операторным. Это метод, но немножко специфический. Название операторного метода состоит из ключевого слова operator и символа оператора, для которого определяется способ применения к объектам класса. Например, если мы хотим определить операцию сложения для объектов класса с помощью оператора +, то в классе нужно описать операторный метод под названием operator+. Если в классе описан операторный метод с названием operator*, то для объектов класса определена операция "умножения": к таким объектам можно применять оператор умножения *. Ну и так далее.


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

    Но мало знать название операторного метода. Есть некоторые требования, которым должны соответствовать операторные методы. Вот они.


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

    Выше речь шла о бинарном операторе +. У бинарного оператора два операнда (в выражении А+В операнды - это А и В). Но бывают операторы унарные, у которых один операнд. Примером унарного оператора может быть инкремент ++ или декремент --. Если обрабатывается выражение вида А++ и А является объектом класса, в котором описан операторный метод с названием operator++, то именно этот метод будет вызван для обработки выражения А++. Поскольку операторный метод определен для унарного оператора, то у метода всего один аргумент. Этим аргументом методу будет передан операнд А.


    В языке C# перегружаться могут многие операторы, но не все. Например, среди бинарных операторов для перегрузки доступны такие: +, -, *, /, %, &, |, ^, << и >>. Также можно перегружать следующие унарные операторы: +, -, !, ~, ++, --, true и false. Несложно заметить, что выше перечислены в основном арифметические и побитовые операторы.


Операторы "плюс" + и "минус" - упомянуты и среди бинарных, и среди унарных. Ошибки здесь нет, поскольку данные операторы могут использоваться и как унарные, и как бинарные. В выражениях вида А+В и A-В операторы используются как бинарные. Но еще операторы "плюс" и "минус" могут использоваться в следующем формате: или . Здесь речь идет об унарных операторах. С унарным оператором "минус" мы сталкиваемся каждый раз, когда записываем отрицательные числа: унарный оператор "минус" служит индикатором отрицательного числа. Унарный оператор "плюс" может использоваться как индикатор положительного числа. Но на практике он обычно не используется. Тем не менее, если мы имеем дело с объектами, то вполне можем использовать с этими объектами не только бинарные, но и унарные операторы "плюс" и "минус". Для этого достаточно в соответствующем классе описать операторные методы для указанных операторов.

    Отдельного внимания заслуживают операторы true и false. Речь идет о том, что можно определить способ проверки объекта на предмет "истинности" или "ложности". Объекты, для которых определена такая проверка (перегружены операторы true и false), могут использоваться в качестве условий в условных и циклических конструкциях. Операторы true и false перегружаются только в паре: или оба, или ни одного. Перегрузке этих операторов будет посвящен отдельный шаг.


    Перегружать можно и операторы сравнения, но такие операторы должны перегружаться парами: == и !=, <; и >, <= и >=. Также в языке С# есть специальные операторы приведения типа, которые позволяют задавать закон преобразования объекта одного типа в объект другого типа. В пользовательском классе можно описать оператор явного приведения типа (explicit-форма) или неявного приведения типа (implicit-форма).

    Не перегружаются сокращенные операторы присваивания, такие как +=, -=, *=, /=, %=, &=, |=, ^=, <<= и >>=. Но при этом мы можем так переопределить базовые операторы (имеются в виду бинарные операторы +, -, *, /, %, &, |, ^, << и >>), что удастся использовать и сокращенные формы оператора присваивания. Похожая ситуация имеет место с логическими операторами && и || - они не перегружаются. Однако если "правильным образом" перегрузить операторы & и |, то в программном коде к операндам, являющимся объектами класса с перегруженными операторами & и |, можно будет применять и операторы && и ||.


Ситуацию с "правильной перегрузкой" операторов & и | (для возможности использования операторов && и ||) мы рассмотрим отдельно.

    Есть операторы, которые не перегружаются. Среди них:

В том числе не перегружается оператор [] "квадратные скобки" (в общем случае это оператор, который позволяет индексировать объекты - то есть указывать в квадратных скобках после имени объекта индекс или индексы). Вместе с тем в языке C# в классах можно определять индексаторы. Через механизм создания индексаторов реализуется возможность индексировать объекты.


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

    Далее мы более подробно и на конкретных примерах рассмотрим способы перегрузки разных групп операторов.

    На следующем шаге мы рассмотрим перегрузку арифметических и побитовых операторов.




Предыдущий шаг Содержание Следующий шаг