4. 4
Нельзя перегружать
[] – функционал этого оператора предоставляют
индексаторы
() – функционал этого оператора предоставляют
методы преобразования типов
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
краткие формы оператора присваивания будут
автоматически доступны при перегрузке
соответствующих операторов (+, -, * …).
Известно, что в Си-шарп существует ряд операторов для работы со встроенными типами данных. Это операторы «+», «-», «!», «==», «!=» и т.д. Например, бинарный оператор «+» выполняет операцию сложения над численными типами данных. Этот же самый оператор над строками выполняет конкатенацию (склеивание двух строк). Это происходит потому, что оператор «+» перегружен в классе String.
Для перегрузки оператора служит ключевое слово operator, определяющее операторный метод, который, в свою очередь, определяет действие оператора относительно своего класса. Существуют две формы операторных методов (operator): одна - для унарных операторов, другая - для бинарных.
Простыми словами, перегрузка оператора - это реализация своего собственного функционала этого оператора для конкретного класса.
Перегрузка оператора реализуется похожим способом на перегрузку методов. Здесь используется ключевое слово operator.
Перегрузка операторов – это мощная и недостаточно используемая (но часто неправильно используемая) возможность, способная сделать код более простым, а использование объектов - более интуитивно-понятным.
Добавление нескольких простых перегруженных операторов в класс или структуру даст вам возможность:
выполнять преобразования в/ из вашего типа (и) в другие типы
производить математические/логические операции над вашим типом и над ним самим или над другими типами
Ключевое слово explicit объявляет оператор преобразования определяемого пользователем типа, который должен быть вызван с помощью приведения.
Ключевое слово implicit служит для объявления неявного оператора преобразования пользовательского типа. Этот оператор обеспечивает неявное преобразование между пользовательским типом и другим типом, если при преобразовании исключается утрата данных.
Ключевое слово operator используется для перегрузки встроенного оператора или выполнения пользовательского преобразования в объявлении класса или структуры.
Exmpl1
Бинарные операторы принимают два аргумента. Могут быть перегружены следующие операторы: +, -, *, /, %, &, |, ^, &lt;&lt;, &gt;&gt;.
Примечание: Важно, чтобы вы не делали ничего неожиданного при использовании операторов, двуместных или других.
Обычно эти операторы довольно логичны. Для начала рассмотрим +. Он обычно вычисляет сумму двух аргументов.
Приведу пример перегрузки оператора «+» для сложения объектов класса деньги (Money). Деньги характеризуются количеством и валютой. Если добавлять рубли к рублям, то всё будет корректно. Но если необходимо суммировать доллары и рубли это уже нужно как-то обрабатывать.
В случае разных валют можно просто выбросить исключение, что валюты разные, или же переводить одну валюту по курсу в другую и суммировать деньги в одной валюте.
Унарные операторы принимают только один аргумент. Могут быть перегружены следующие операторы: +, -, !, ~, ++, --, true, false. Для большинства типов не нужно реализовывать все эти операторы, поэтому реализуйте только необходимые вам!
int a = 2, b = 3, c, d = 3; c = a + ++b; // c = 6, сначала инкремент, потом сложение с = a + d++; // c = 5, сначала сложение, потом инкремент
Везде где можно использовать инкрементацию/декрементацию стоит это делать, так как она работает быстрее оператора сложения/вычитания.
int a = 2, b = 3;a += b; // равноценно выражению a = a + b; a -= b; // равноценно выражению a = a - b; a *= b; // равноценно выражению a = a * b; a /= b; // равноценно выражению a = a / b; a %= b; // равноценно выражению a = a % b;
Операторы сравнения принимают два аргумента. Могут быть перегружены следующие операторы. [==, !=], [&lt;, &gt;], [&lt;=, &gt;=]. Они сгруппированы в квадратных скобках, так как их нужно реализовывать попарно.
При использовании == and != также необходимо заменить Equals(object o) и GetHashCode().
exmpl5
Операторы отношения, например == и &lt;, могут также перегружаться, причем очень просто. Как правило, перегруженный оператор отношения возвращает логическое значение true и false. Это вполне соответствует правилам обычного применения подобных операторов и дает возможность использовать их перегружаемые разновидности в условных выражениях. Если же возвращается результат другого типа, то тем самым сильно ограничивается применимость операторов отношения.
Exmpl6
Ключевые слова true и false можно также использовать в качестве унарных операторов для целей перегрузки. Перегружаемые варианты этих операторов позволяют определить назначение ключевых слов true и false специально для создаваемых классов.
После перегрузки этих ключевых слов в качестве унарных операторов для конкретного класса появляется возможность использовать объекты этого класса для управления операторами if, while, for и do-while или же в условном выражении ?.
Операторы true и false должны перегружаться попарно, а не раздельно.
Exmpl7
Как вам должно быть уже известно, в C# предусмотрены следующие логические операторы: &, |, !, && и ||. Из них перегрузке, безусловно, подлежат только операторы &, | и !. Тем не менее, соблюдая определенные правила, можно извлечь также пользу из укороченных логических операторов && и ||.
Иногда объект определенного класса требуется использовать в выражении, включающем в себя данные других типов. В одних случаях для этой цели оказывается пригодной перегрузка одного или более операторов, а в других случаях — обыкновенное преобразование типа класса в целевой тип.
Для подобных ситуаций в C# предусмотрена специальная разновидность операторного метода, называемая оператором преобразования.
Такой оператор преобразует объект исходного класса в другой тип. Операторы преобразования помогают полностью интегрировать типы классов в среду программирования на C#, разрешая свободно пользоваться классами вместе с другими типами данных, при условии, что определен порядок преобразования в эти типы.
Exmpl7
Существуют две формы операторов преобразования: явная и неявная.
где целевой_тип обозначает тот тип, в который выполняется преобразование; исходный_тип — тот тип, который преобразуется; значение — конкретное значение, приобретаемое классом после преобразования. Операторы преобразования возвращают данные, имеющие целевой_тип, причем указывать другие возвращаемые типы данных не разрешается.
Неявное преобразование означает, что можно напрямую присваивать экземпляр одного типа другому.
Если оператор преобразования указан в неявной форме (implicit), то преобразование вызывается автоматически, например, в том случае, когда объект используется в выражении вместе со значением целевого типа.
----
Если же оператор преобразования указан в явной форме (explicit), то преобразование вызывается в том случае, когда выполняется приведение типов. Для одних и тех же исходных и целевых типов данных нельзя указывать оператор преобразования одновременно в явной и неявной форме.
Оператор неявного преобразования применяется автоматически в следующих случаях: когда в выражении требуется преобразование типов; методу передается объект; осуществляется присваивание и производится явное приведение к целевому типу.
С другой стороны, можно создать оператор явного преобразования, вызываемый только тогда, когда производится явное приведение типов.
На операторы преобразования накладывается ряд следующих ограничений:
Помимо указанных выше ограничений, имеется ряд рекомендаций, которыми обычно руководствуются при выборе операторов явного или неявного преобразования. Несмотря на все преимущества неявных преобразований, к ним следует прибегать только в тех случаях, когда преобразованию не свойственны ошибки.
Во избежание подобных ошибок неявные преобразования должны быть организованы только в том случае, если удовлетворяются следующие условия.
Во-первых, информация не теряется, например, в результате усечения, переполнения или потери знака.
И во-вторых, преобразование не приводит к исключительной ситуации. Если же неявное преобразование не удовлетворяет этим двум условиям, то следует выбрать явное преобразование.
Если вы не использовали ее раньше, опробуйте ее в работе – она может оказаться для вас полезным инструментом.
Не злоупотребляйте ими. Если оператор или преобразование точно никогда не понадобятся, или не очевидно, каким будет результат, не реализуйте его.
Не используйте их неправильно. Можно сделать так, чтобы ++ уменьшал значения, но этого определенно не нужно делать!
Будьте очень осторожны при неявном преобразовании ваших классов или структур в другие типы.