Відомо, що в Сі-шарп існує ряд операторів для роботи з вбудованими типами даних. Це оператори «+», «-», «!», «==», «! =» І т.д. Наприклад, бінарний оператор «+» виконує операцію додавання над чисельними типами даних. Цей же самий оператор над рядками виконує конкатенацію (склеювання двох рядків). Це відбувається тому, що оператор «+» перевантажений в класі String.
Простими словами, перевантаження оператора - це реалізація свого власного функціоналу цього оператора для конкретного класу.
Перевантаження оператора реалізується схожим способом на перевантаження методів. Тут використовується ключове слово operator. Загальна структура перевантаження операторів має наступний вигляд:
Перевантаження унарного * оператора:
public static [повернений тип] operator [оператор] ([тип_операнда] [операнд])
{
// функціонал оператора
}
Перевантаження бінарного * оператора:
public static [повернений тип] operator [оператор] ([тип_операнда1] [операнд1], [тип_операнда2] [операнд2])
{
// функціонал оператора
}
* Що таке унарні і бінарні оператори читайте в уроці Арифметичні та логічні операції
Модифікатори public і static є обов'язковими. На місці [оператор] може стояти будь-який оператор, який можна перевантажити. Не всі оператори в Сі-шарп дозволяється перевантажувати. Нижче наведені оператори які можна перевантажувати, і ті які не можна:
Можна перевантажувати
Унарні оператори: +, -,!, ++, -, True, false
Бінарні оператори: +, -, *, /,%, &, |, ^, <<, >>, ==,! =, <,>, <=,> =
Не можна перевантажувати
[] - Функціонал цього оператора надають індексатори
() - Функціонал цього оператора надають методи перетворення типів
+ =, - =, * =, / =,% =, & =, | =, ^ =, << =, >> = Короткі форми оператора присвоювання будуть автоматично доступні при перевантаженні відповідних операторів (+, -, * ...) .
Перевантаження бінарних операторів
Наведу приклад перевантаження оператора «+» для додавання об'єктів класу гроші (Money). Гроші, характеризуються кількістю і валютою. Якщо додавати гривні до гривень, то все буде коректно. Але якщо необхідно підсумовувати долари і гривніі це вже потрібно якось обробляти. У разі різних валют можна просто викинути виняток, що валюти різні, або ж переводити одну валюту за курсом в іншу і підсумовувати гроші в одній валюті. Нижче в прикладі простий варіант з викиданням виключення:
public class Money
{
public decimal Amount {get; set; }
public string Unit {get; set; }
public Money (decimal amount, string unit)
{
Amount = amount;
Unit = unit;
}
public static Money operator + (Money a, Money b) // перевантаження оператора «+»
{
if (a.Unit! = b.Unit)
throw new InvalidOperationException ("Не можна підсумувати гроші в різних валютах");
return new Money (a.Amount + b.Amount, a.Unit);
}
}
class Program
{
static void Main (string [] args)
{
Money myMoney = new Money (100, "USD");
Money yourMoney = new Money (100, "GR");
Money hisMoney = new Money (50, "USD");
Money sum = myMoney + hisMoney; // 150 USD
sum = yourMoney + hisMoney; // Виняток - різні валюти
Console.ReadLine ();
}
}
Перевантаження унарних операторів
Візьмемо програму з першого прикладу з грошима, і перевантажимо там унарні оператори «++», «-» (додавання / віднімання 1 одиниці грошей):
public class Money
{
public decimal Amount {get; set; }
public string Unit {get; set; }
public Money (decimal amount, string unit)
{
Amount = amount;
Unit = unit;
}
public static Money operator + (Money a, Money b)
{
if (a.Unit! = b.Unit)
throw new InvalidOperationException ("Не можна підсумувати гроші в різних валютах");
return new Money (a.Amount + b.Amount, a.Unit);
}
public static Money operator ++ (Money a) // перевантаження «++»
{
a.Amount ++;
return a;
}
public static Money operator - (Money a) // перевантаження «-»
{
a.Amount--;
return a;
}
}
class Program
{
static void Main (string [] args)
{
Money myMoney = new Money (100, "USD");
myMoney ++; // 101 USD
Console.ReadLine ();
}
}
Також існує можливість перевантаження самого операторного методу. Це означає що в класі може бути декілька перевантажень одного оператора за умови що вхідні параметри будуть відрізнятися типом даних (наприклад, коли необхідно скласти об'єкт класу і рядок):
public class Money
{
public decimal Amount {get; set; }
public string Unit {get; set; }
public Money (decimal amount, string unit)
{
Amount = amount;
Unit = unit;
}
public static Money operator + (Money a, Money b)
{
if (a.Unit! = b.Unit)
throw new InvalidOperationException ("Не можна підсумувати гроші в різних валютах");
return new Money (a.Amount + b.Amount, a.Unit);
}
public static string operator + (string text, Money a)
{
return text + a.Amount + "" + a.Unit;
}
}
class Program
{
static void Main (string [] args)
{
Money myMoney = new Money (100, "USD");
Console.WriteLine ("У мене зараз" + myMoney); // "У мене зараз 100 USD"
Console.ReadLine ();
}
}
Домашнє завдання
Завдання буде базуватися на прикладі цього уроку. Необхідно реалізувати другий варіант додавання грошей - щоб можна було підсумувати гроші в різних валютах. Для цього створіть окремий клас, який надаватиме механізм конвертації грошей по заданому курсу. Крім цього, перевантажите для класу Money оператор порівняння «==» (при перевантаженні даного оператора, обов'язковою є і перевантаження протилежного йому оператора «! =»).
PS. Не забудьте поділитися з друзями цією статтею за допомогою кнопок соціальних мереж.