Чтобы позволить пользовательскому типу по-своему отвечать на встроенные операции, в 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;

<p>Операции += и -=</p>

Если вы изучаете 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);

}

<p>Перегрузка унарных операций</p>

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

}

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

Вы можете помнить из материала главы 3, что System.Object.Equals() можно переопределить, чтобы сравнение типов выполнялось на основе значений (а не ссылок). Если вы переопределите Equals() (и связанный с Equals() метод System.Object.GetHashCode()), то будет очень просто задать перегрузку операций проверки на тождественность (== и !=). Для иллюстрации мы рассмотрим обновленный тип Point.

// Такая 'инкарнация' Point задает также перегрузку операций == и !=.

Перейти на страницу:

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