Очевидными примерами соответствующей перегрузки операторов являются любые классы, которые ведут себя так же, как и числа. Таким образом, классы 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>.
Реальные проблемы с перегрузкой операторов возникают, когда программист предполагает, что класс будет вести себя одинаково, но на самом деле он ведет себя по-другому. Такого рода семантическое столкновение - это то, что я предлагаю, важно избегать.