Шрифт:
Интервал:
Закладка:
// Операция + со строками.
string s1 = "Hello";
string s2 = " world!";
string s3 = s1 + s2; // s3 теперь имеет значение "Hello World!"
Операция + функционирует специфическим образом на основе типа предоставленных данных (в рассматриваемом случае строкового или целочисленного). Когда операция + применяется к числовым типам, в результате выполняется суммирование операндов, а когда к строковым типам — то конкатенация строк.
Язык C# дает возможность строить специальные классы и структуры, которые также уникально реагируют на один и тот же набор базовых лексем (вроде операции +). Хотя не каждая операция C# может быть перегружена, перегрузку допускают многие операции (табл. 11.1).
Перегрузка бинарных операций
Чтобы проиллюстрировать процесс перегрузки бинарных операций, рассмотрим приведенный ниже простой класс Point, который определен в новом проекте консольного приложения по имени OverloadedOps:
using System;
namespace OverloadedOps
{
// Простой будничный класс С#.
public class Point
{
public int X {get; set;}
public int Y {get; set;}
public Point(int xPos, int yPos)
{
X = xPos;
Y = yPos;
}
public override string ToString()
=> $"[{this.X}, {this.Y}]";
}
}
Рассуждая логически, суммирование объектов Point имеет смысл. Например, сложение двух переменных Point должно давать новый объект Point с просуммированными значениями свойств X и Y. Конечно, полезно также и вычитать один объект Point из другого. В идеале желательно иметь возможность записи примерно такого кода:
using System;
using OverloadedOps;
// Сложение и вычитание двух точек?
Console.WriteLine("***** Fun with Overloaded Operators *****n");
// Создать две точки.
Point ptOne = new Point(100, 100);
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})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();
Тем не менее, с существующим видом класса Point вы получите ошибки на этапе компиляции, потому что типу Point не известно, как реагировать на операцию + или -. Для оснащения специального типа способностью уникально реагировать на встроенные операции язык C# предлагает ключевое слово operator, которое может использоваться только в сочетании с ключевым словом static. При перегрузке бинарной операции (такой как + и -) вы чаще всего будете передавать два аргумента того же типа, что и класс, определяющий операцию (Point в этом примере):
// Более интеллектуальный тип Point.
public class Point
{
...
// Перегруженная операция +.
public static Point operator + (Point p1, Point p2)
=> new Point(p1.X + p2.X, p1.Y + p2.Y);
// Перегруженная операция -.
public static Point operator - (Point p1, Point p2)
=> new Point(p1.X - p2.X, p1.Y - p2.Y);
}
Логика, положенная в основу операции +, предусматривает просто возвращение нового объекта Point, основанного на сложении соответствующих полей входных параметров Point. Таким образом, когда вы пишете p1 + р2, "за кулисами" происходит следующий скрытый вызов статического метода operator +:
// Псевдокод: Point рЗ = Point.operator+ (pi, р2)
Point p3 = p1 + p2;
Аналогично выражение pi - р2 отображается так:
// Псевдокод: Point р4 = Point.operator- (pi, р2)
Point p4 = p1 - p2;
После произведенной модификации типа Point программа скомпилируется и появится возможность сложения и вычитания объектов Point, что подтверждает представленный далее вывод:
- Понимание SQL - Мартин Грубер - Базы данных