// Самая обычная структура C#.
public struct Point {
private int x, y;
public Point(int xPos, int yPos) {
x = xPos ; у = yPos;
}
public override string ToString() {
return string.Format("[{0}, {1}]", this.x, this.у);
}
}
Можно, скажем, рассмотреть сложение типов Point. Можно также вычесть один тип Point из другого. Например, вы можете записать, следующий программный код.
// Сложение и вычитание двух точек.
static vоid Main(string [] args) {
Console.WriteLine("*** Забавы с перегруженными операциями ***\n");
// Создание двух точек.
Point ptOne = new Point(100, 100);
Point ptTwo = new Point (40, 40);
Console.WriteLine("ptOne = {0}", ptOne);
Console.WriteLine("ptTwo = {0}", ptTwo);
// Сложение точек в одну большую точку?
Console.WriteLine("ptOne + ptTwo: {0} ", ptOne + ptTwo);
// Вычитание одной точки из другой дает меньшую точку?
Console.WriteLine("ptOne – ptTwo: {0} ", ptOne – ptTwo);
Console.ReadLine();
}
Чтобы позволить пользовательскому типу по-своему отвечать на встроенные операции, в C# предлагается ключевое слово operator, которое можно использовать только со статическими методами. Перегруженной бинарной операции (такой, как + или -) на вход подаются два аргумента, которые имеют тип определяющего класса (в данном примере это Point), как показывает следующий программный код.
// Более 'интеллектуальный' тип Point.
public struct Point {
…
// перегруженная операция +
public static Point operator+(Point p1, Point p2) { return new Point(p1.x + p2.x, p1.y + p2.y); }
// перегруженная операция -
public static Point operator–(Point p1, Point p2) { return new Point(p1.x – p2.x, p1.y – p2.y); }
}
По логике операция + должна просто возвратить совершенно новый объект Point, полученный в результате суммирования соответствующих полей входных параметров Point. Поэтому, когда вы пишете pt1 + pt2, можете представлять себе следующий скрытый вызов статического метода операции +.
// р3 = Point.операция+(p1, р2)
р3 = p1 + р2;
Точно так же p2 – p2 отображается в следующее.
// р3 = Point.операция-(p1, р2)
р3 = p1 – p2;
Если вы изучаете C#, уже имея опыт использования C++, то можете обратить внимание на отсутствие возможности перегрузки операторных сокращений, включающих операцию присваивания (+=, -= и т.д.). Не волнуйтесь, в C# операторные сокращения с присваиванием моделируются автоматически, если тип предполагает перегрузку соответствующей бинарной операции. Поэтому, поскольку структура Point уже использует перегрузку операций + и -, вы можете записать следующее.
// Перегрузка бинарных операций автоматически влечет перегрузку
// операторных сокращений с присваиванием.
static void Main(string[] args) {
// Автоматическая перегрузка +=
Point ptThree = new Point(90, 5);
Console.WriteLine("ptThree = {0}", ptThree);
Console.WriteLine("ptThree +=ptTwo: {0} ", ptThree += ptTwo);
// Автоматическая перегрузка -=
Point ptFour = new Point(0, 500);
Console.WriteLine("ptFour = {0}", ptFour);
Console.WriteLine("ptFour -= ptThree: {0}", ptFour -= ptThree);
}
Перегрузка унарных операций
В C# также позволяется перегрузка унарных операций, таких как, например, ++ и --. При перегрузке унарной операции вы тоже должны с помощью ключевого слова operator определить статический метод, но в данном случае передается только один параметр, который должен иметь тип, соответствующий определяющему классу или структуре. Например, если добавить в Point следующие перегруженные операции
public struct Point {
…
// Добавление 1 к поступившему Point.
public static Point operator++(Point p1) { return new Point(p1.x+1, p1.y+1); }
// Вычитание 1 от поступившего Point.
public static Point operator--(Point p1) { return new Point(p1.x-1, p1.y-1); }
}
то вы получите возможность увеличивать или уменьшать на единицу значения X и Y объекта Point, как показано ниже.
static void Main(string[] args) {
…
// Применение унарных операций ++ и -- к Point.
Console.WriteLine("++ptFive = {0}", ++ptFive);
Console.WriteLine("--ptFive = {0}", --ptFive);
}
Перегрузка операций проверки на тождественность
Вы можете помнить из материала главы 3, что System.Object.Equals() можно переопределить, чтобы сравнение типов выполнялось на основе значений (а не ссылок). Если вы переопределите Equals() (и связанный с Equals() метод System.Object.GetHashCode()), то будет очень просто задать перегрузку операций проверки на тождественность (== и !=). Для иллюстрации мы рассмотрим обновленный тип Point.
Читать дальше