Console.WriteLine("ptOne != ptTwo: {0}", ptOne != ptTwo);
}
Как видите, здесь два объекта сравниваются с помощью операций == и !=, а не с помощью "менее естественного" вызова Object.Equals. При использовании перегрузки операций проверки на тождественность для класса имейте в виду, что в C# требуется, чтобы при переопределении операции –
Перегрузка операций сравнения
Из материала главы 7 вы узнали о том, как реализовать интерфейс IComparable, чтобы иметь возможность сравнения подобных объектов. В дополнение к этому для того же класса вы можете использовать перегрузку операций сравнения (‹, ›, ‹= и ›=). Подобно операциям проверки на тождественность, в C# требуется, чтобы при перегрузке ‹ выполнялась и перегрузка ›. Это же касается и операций ‹= и ›=. Если тип Point использует перегрузку операций сравнения, пользователь объекта получает возможность сравнивать объекты Point так, как показано ниже.
// Использование перегруженных операций ‹ и ›.
static void Main(string[] args) {
…
Console.WriteLine("ptOne ‹ ptTwo: {0}
Console.WriteLine("ptOne › ptTwo: {0}", ptOne › ptTwo);
}
В предположении о том, что интерфейс IComparable реализован, перегрузка операций сравнения оказывается тривиальной. Вот как может выглядеть обновленное определение класса.
// Можно сравнивать объекты Point с помощью операций сравнения.
public struct Point: IComparable {
…
public int CompareTo(object obj) {
if (obj is Point) {
Point p = (Point)obj;
if (this.x › p.x && this.y › p.y) return 1;
if (this.x ‹ p.x && this.y ‹ p.y) return -1;
else return 0;
} else throw new ArgumentException;
}
public static bool operator‹(Point p1, Point p2) { return(p1.CompareTo(р2) ‹ 0); }
public static bool operator›(Point p1, Point p2) { return(p1.CompareTo(p2) › 0); }
public static bool operator‹=(Point p1, Point p2) { return(p1.CompareTo(p2) ‹= 0); }
public statiс bool operator›=(Point p1, Point p2) { return(p1.CompareTo(p2) ›= 0); }
}
Внутреннее представление перегруженных операций
Подобно любому элементу программы C#, перегруженные операции представляются специальными элементами синтаксиса CIL. Откройте, например, компоновочный блок OverloadedOps.exe с помощью ildasm.exe. Как показано на рис. 9.1, перегруженные операции внутри блока представляются скрытыми методами (это, например, op_Addition, oр_Subtraction, op_Equality и т.д.).
Теперь, если рассмотреть CIL-инструкции для метода op_Addition, то вы обнаружите, что csc.exe добавляет в метод ключевое слово specialname.
.method public hidebysig specialname static valuetype OverloadedOps.Point op_Addition(valuetype OverloadedsOps.Point p1, valuetype OverloadedOps.Point p2) cil managed {
…
}
Рис. 9.1. В терминах CIL перегруженные операции отображаются в скрытые методы
Итак, любая операция, допускающая перегрузку, сводится в терминах CIL к специальному именованному методу. В табл. 9.2 раскрывается соответствие имен типичных операций C# и методов CIL.
Таблица 9.2. Соответствие имен операций C# и методов CIL
| Внутренняя операция C# | Представление CIL |
|---|---|
| –- | op_Decrement |
| ++ | op_Increment |
| + | op_Addition |
| – | op_Subtraction |
| * | op_Multiply |
| / | op_Division |
| == | op_Equality |
| › | op_GreaterThan |
| ‹ | op_LessThan |
| != | op_Inequality |
| ›= | op_GreaterThanOrEqual |
| ‹= | op_LessThanOrEqual |
| –= | op_SubtractionAssignment |
| += | op_AdditionAssignment |
Использование перегруженных операций в языках, не поддерживающих перегрузку операций