Console.WriteLine("ptOne != ptTwo: {0}", ptOne != ptTwo);

}

Как видите, здесь два объекта сравниваются с помощью операций == и !=, а не с помощью "менее естественного" вызова Object.Equals. При использовании перегрузки операций проверки на тождественность для класса имейте в виду, что в C# требуется, чтобы при переопределении операции – обязательно переопределялась и операция != (если вы забудете это сделать, компилятор вам напомнит).

<p>Перегрузка операций сравнения</p>

Из материала главы 7 вы узнали о том, как реализовать интерфейс IComparable, чтобы иметь возможность сравнения подобных объектов. В дополнение к этому для того же класса вы можете использовать перегрузку операций сравнения (‹, ›, ‹= и ›=). Подобно операциям проверки на тождественность, в C# требуется, чтобы при перегрузке ‹ выполнялась и перегрузка ›. Это же касается и операций ‹= и ›=. Если тип Point использует перегрузку операций сравнения, пользователь объекта получает возможность сравнивать объекты Point так, как показано ниже.

// Использование перегруженных операций ‹ и ›.

static void Main(string[] args) {

 …

 Console.WriteLine("ptOne ‹ ptTwo: {0}", ptOne ‹ ptTwo);

 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); }

}

<p>Внутреннее представление перегруженных операций</p>

Подобно любому элементу программы 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
<p>Использование перегруженных операций в языках, не поддерживающих перегрузку операций</p>
Перейти на страницу:

Похожие книги