Введение
Наряду с методами в классах и структурах мы можем также определять операторы.
Операторы могут быть перегружены, чтобы обеспечить более естественный синтаксис для пользовательских типов. В большей степени это актуально для реализации пользовательских структур, представляющих довольно простые типы данных.
Перегрузка операторов позволяет реализовать удобный синтаксис для работы с классами в программировании. Эта возможность является одним из ключевых преимуществ объектно-ориентированного программирования на C#.
Перегрузка операторов С# делает код красивее. Мы задаем, редактируем, или сами можем придумывать поведение определенного нами класса. Используя унарные, бинарные операторы, операторы сравнения и логические операторы мы задаем определенное действие компилятору.
Перегружены могут быть следующие операторы:
+ - * / ++ -- ! ~ % & | ^ == != < << >> >
Синтаксис
// перегрузка унарного оператора public static тип operator primer(тип_параметра операнд)
{
// запросы
}
// перегрузка бинарного оператора public static тип operator primer (тип_параметра1 операнд1, тип_параметра1 операнд2)
{
// запросы
}
Метод объявляется модификаторами public и static. Оператор, который перегружается должен быть одного типа с операндами.
Пример
Давайте разберем перегрузку операторов на примере, который предлагает официальная документация языка программирования C#
Разбор кода
Думаю на первый взгляд пример, который дает официальная документации очень сложный и не понятный. Чтобы внести ясность разберем его постепенно - шаг за шагом.
Шаг 1: Создадим структуру Fraction
Данная структура будет представлять собой дробь. Соответственно у нее будут: числитель, знаменатель в виде полей и конструктор, для передачи значений в эти поля. (Рис.2)
Шаг 2: Переопределим метод ToString() у данной структуры, что получать при вызове методы вывод дроби удобный для понимания. (Рис.3)
Исходя из данного кода , при вызове метода у объекта структуры мы получим строку вида числитель/знаменатель
public override string ToString() => $"{num} / {den}"; // перегрузка метода
Шаг 3: Перегрузим оператор `+` (Рис.4)
Перегрузка оператора не сложения, а указания на положительность дроби
public static Fraction operator +(Fraction a) => a;
Шаг 4: Перегрузим оператор `-`, который сделает дробь отрицательной (Рис.5)
public static Fraction operator -(Fraction a) => new Fraction(-a.num, a.den);
Шаг 5: Перегрузка оператора сложения (Рис.6)
В данном случае мы перегружаем бинарный оператор, он принимает две дроби (A и B), и в результате возвращает новую дробь, которая будет являться результатом сложения двух дробей
public static Fraction operator +(Fraction a, Fraction b) => new Fraction(a.num * b.den + b.num * a.den, a.den * b.den);
Шаг 6: Перегрузка оператора вычитания (Рис.7)
В данном случае мы перегружаем бинарный оператор, он принимает две дроби (A и B), и в результате возвращает новую дробь, которая будет являться результатом вычитания двух дробей
public static Fraction operator -(Fraction a, Fraction b) => a + (-b);
Шаг 7: Перегрузка оператора вычитания (Рис.8)
В данном случае мы перегружаем бинарный оператор, он принимает две дроби (A и B), и в результате возвращает новую дробь, которая будет являться результатом умножения двух дробей
public static Fraction operator *(Fraction a, Fraction b) => new Fraction(a.num * b.num, a.den * b.den);
Шаг 8: Перегрузка оператора вычитания (Рис.9)
В данном случае мы перегружаем бинарный оператор, он принимает две дроби (A и B), и в результате возвращает новую дробь, которая будет являться результатом деления двух дробей
public static Fraction operator /(Fraction a, Fraction b)
{
if (b.num == 0)
{
throw new DivideByZeroException();
}
return new Fraction(a.num * b.den, a.den * b.num);
}
Шаг 9: Теперь мы можем использовать операторы + - * / для нашей структуры Fraction и для них будет выполнять логика описанная в перегрузке. Грубо говоря мы сказали компилятору , то как выглядят различные виды операций (математических) для нашей структры. (Рис.10)
var a = new Fraction(5, 4);
var b = new Fraction(1, 2);
Console.WriteLine(-a); // output: -5 / 4
Console.WriteLine(a + b); // output: 14 / 8
Console.WriteLine(a - b); // output: 6 / 8
Console.WriteLine(a * b); // output: 5 / 8
Console.WriteLine(a / b); // output: 10 / 4
Перегрузка операторов C# заключение
Важно помнить, что на перегрузку операторов есть ограничения. Нельзя использовать оператор присваивания =. Кроме них есть операторы, которые в языке С# еще не определены. Так же, нельзя изменить количество операндов. Для бинарных операторов нельзя задавать три аргумента. Поскольку в его синтаксисе указан только два аргумента.
Чтобы создать легкий интерфейс, важно использовать перегрузки операторов. К тому же, учитывая их, вы упрощаете набранный код программы. Данное действие над операторами интересно тем, что пользователь сможет внедрить в программу свои правила и требования, контролируя функции операторов.