На этом шаге мы приведем общие сведения о механизме перегрузки операторов.
Как мы уже знаем, в языке C# есть много различных операторов, которые позволяют выполнять всевозможные операции со значениями разных типов. Например, мы можем с помощью оператора "плюс" + сложить два числа и получить в результате число. Мы можем "сложить" с помощью того же оператора два текстовых значения и получить в результате текст. Существуют и другие ситуации, когда мы можем использовать оператор + (или какой-нибудь иной оператор). Все они предопределены: то есть случаи, когда мы можем использовать тот или иной оператор, определены заранее и зависят от типа операндов, участвующих в операции. Другими словами, имеется ограниченное количество ситуаций, в которых могут использоваться операторы языка С#, а результат выполнения операций зависит от типа операндов. Например, мы можем к тексту прибавить число, но не можем текст умножить на число. В этом смысле наши возможности ограничены и строго детерминированы. Но есть в языке C# очень мощный и эффективный механизм, который связан с перегрузкой операторов. Основная идея в том, что для объектов пользовательских классов (то есть классов, которые мы описываем в программе) доопределяется действие встроенных операторов языка С#. Скажем, описывая класс, возможно путем несложных манипуляций добиться того, что объекты этого класса можно будет складывать, как числа. Или, например, к объекту класса можно будет прибавить число, и так далее. Смысл каждой такой операции определяем мы, когда описываем класс.
Чтобы определить способ применения того или иного оператора к объектам класса, в классе описывается специальный метод, который называется операторным. Это метод, но немножко специфический. Название операторного метода состоит из ключевого слова operator и символа оператора, для которого определяется способ применения к объектам класса. Например, если мы хотим определить операцию сложения для объектов класса с помощью оператора +, то в классе нужно описать операторный метод под названием operator+. Если в классе описан операторный метод с названием operator*, то для объектов класса определена операция "умножения": к таким объектам можно применять оператор умножения *. Ну и так далее.
Но мало знать название операторного метода. Есть некоторые требования, которым должны соответствовать операторные методы. Вот они.
Выше речь шла о бинарном операторе +. У бинарного оператора два операнда (в выражении А+В операнды - это А и В). Но бывают операторы унарные, у которых один операнд. Примером унарного оператора может быть инкремент ++ или декремент --. Если обрабатывается выражение вида А++ и А является объектом класса, в котором описан операторный метод с названием operator++, то именно этот метод будет вызван для обработки выражения А++. Поскольку операторный метод определен для унарного оператора, то у метода всего один аргумент. Этим аргументом методу будет передан операнд А.
В языке C# перегружаться могут многие операторы, но не все. Например, среди бинарных операторов для перегрузки доступны такие: +, -, *, /, %, &, |, ^, << и >>. Также можно перегружать следующие унарные операторы: +, -, !, ~, ++, --, true и false. Несложно заметить, что выше перечислены в основном арифметические и побитовые операторы.
Отдельного внимания заслуживают операторы true и false. Речь идет о том, что можно определить способ проверки объекта на предмет "истинности" или "ложности". Объекты, для которых определена такая проверка (перегружены операторы true и false), могут использоваться в качестве условий в условных и циклических конструкциях. Операторы true и false перегружаются только в паре: или оба, или ни одного. Перегрузке этих операторов будет посвящен отдельный шаг.
Перегружать можно и операторы сравнения, но такие операторы должны перегружаться парами: == и !=, < и >, <= и >=. Также в языке С# есть специальные операторы приведения типа, которые позволяют задавать закон преобразования объекта одного типа в объект другого типа. В пользовательском классе можно описать оператор явного приведения типа (explicit-форма) или неявного приведения типа (implicit-форма).
Не перегружаются сокращенные операторы присваивания, такие как +=, -=, *=, /=, %=, &=, |=, ^=, <<= и >>=. Но при этом мы можем так переопределить базовые операторы (имеются в виду бинарные операторы +, -, *, /, %, &, |, ^, << и >>), что удастся использовать и сокращенные формы оператора присваивания. Похожая ситуация имеет место с логическими операторами && и || - они не перегружаются. Однако если "правильным образом" перегрузить операторы & и |, то в программном коде к операндам, являющимся объектами класса с перегруженными операторами & и |, можно будет применять и операторы && и ||.
Есть операторы, которые не перегружаются. Среди них:
Далее мы более подробно и на конкретных примерах рассмотрим способы перегрузки разных групп операторов.
На следующем шаге мы рассмотрим перегрузку арифметических и побитовых операторов.