Головні арифметичні оператори та оператори порівняння можна пристосувати для використання у власних класах і структурах. Це називається перевантаженням операторів.
У цій статті ґрунтовно розглянуто синтаксис, а також те, які оператори можна перевантажувати, а які ні.
Більшість операторів мають такий вигляд:
static <return type> operaator <operator symbols>(<parameters>);
Оператори приведення мають такий вигляд:
static (explicit|implicit) operator <cast-to-type>(<cast-from-type> <parameter name>);
Оператори поводяться так само, як статичні методи.
Приклади синтаксису:
struct Point
{
decimal x;
decimal y;
public static bool operator ==(Point pt, Point ptOther)
{
return pt.x == ptOther.x && pt.y == ptOther.y;
}
public static bool operator !=(Point pt, Point ptOther)
{
return !(pt == ptOther);
}
public static Point operator *(Point pt, decimal scale)
{
var ptNew = new Point();
ptNew.x = pt.x * scale;
ptNew.y = pt.y * scale;
return ptNew;
}
public static implicit operator Point((decimal x, decimal y) xy)
{
var pt = new Point();
pt.x = xy.x;
pt.y = xy.y;
return pt;
}
public static explicit operator (decimal x, decimal y)(Point pt)
{
return (pt.x, pt.y);
}
}
Часто продуктивно реалізувати метод Equals() і викликати його з оператора ==. Так само для порівнянь можна реалізувати інтерфейс IComparable. В обох випадках можна вбити двох зайців одним каменем, щоправда, трохи більшим.
Зауважмо, що не можна створювати оператори із символів, які не належать до стандартного набору операторів. Можна використовувати лише наявні символи для тих операцій, які, за документацією, можна перевантажувати. Оператори, які можна перевантажувати, перелічено тут.
Зауважмо, що порядок параметрів важливий, коли вони різняться за типом. У наведеному вище прикладі коду pt * 10m є коректним виразом, а 10m * pt не скомпілюється.
У цій документації з перевантаження операторів докладно описано синтаксис.