Очевидными примерами соответствующей перегрузки операторов являются любые классы, которые ведут себя так же, как и числа. Таким образом, классы BigInt (как предлагает Джалайн ), комплексные числа или матричные классы (как предполагает Superbest ) имеют те же операции, что и обычные числа, поэтому очень хорошо отображаются на математические операторы, в то время как операции времени (как предлагает svick ) отображаются на подмножество из этих операций.
Чуть более отвлеченно, операторы могут быть использованы при выполнении набора как операций, так operator+
может быть союз , operator-
может быть дополнением и т.д. Это действительно начинает растягиваться парадигму , хотя, особенно если вы используете сложение или умножения оператора на операцию , которая ISN» т коммутативный , как вы могли бы ожидать, что они будут.
Сам C # имеет отличный пример перегрузки нечисловых операторов. Он использует +=
и -=
для добавления и вычитания делегатов , т.е. регистрирует и отменяет их регистрацию. Это хорошо работает , потому что +=
и -=
операторы работают , как можно было бы ожидать их к, и этот результат в гораздо более лаконичном коде.
Для пуриста одна из проблем со строковым +
оператором состоит в том, что он не коммутативный. "a"+"b"
это не то же самое, что "b"+"a"
. Мы понимаем это исключение для строк, потому что оно очень распространено, но как мы можем определить, будет ли использование operator+
других типов коммутативным или нет? Большинство людей предполагают, что это так, если только объект не похож на строку , но вы никогда не знаете, что люди примут.
Как и со строками, слабые стороны матриц также довольно хорошо известны. Очевидно, что Matrix operator* (double, Matrix)
это скалярное умножение, тогда как, например, Matrix operator* (Matrix, Matrix)
это будет матричное умножение (т. Е. Матрица умножения на скалярное произведение).
Точно так же использование операторов с делегатами настолько очевидно далеко от математики, что вы вряд ли допустите эти ошибки.
Кстати, на конференции ACCU 2011 года Роджер Орр и Стив Лав представили сессию, посвященную тому, что некоторые объекты более равны, чем другие, - взгляд на многие значения равенства, ценности и идентичности . Их слайды можно загрузить , как и Приложение Ричарда Харриса о равенстве с плавающей точкой . Резюме: будь очень осторожен с operator==
драконами!
Перегрузка операторов является очень мощной семантической техникой, но ее легко использовать. В идеале вы должны использовать его только в ситуациях, когда из контекста очень ясно, каково влияние перегруженного оператора. Во многих отношениях a.union(b)
это яснее , чем a+b
и a*b
является гораздо более неясным , чем a.cartesianProduct(b)
, тем более , что результат декартова произведения будет , SetLike<Tuple<T,T>>
а не SetLike<T>
.
Реальные проблемы с перегрузкой операторов возникают, когда программист предполагает, что класс будет вести себя одинаково, но на самом деле он ведет себя по-другому. Такого рода семантическое столкновение - это то, что я предлагаю, важно избегать.