Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Yazyk_C_i_osnovy_platformy_NET.docx
Скачиваний:
16
Добавлен:
11.05.2015
Размер:
198.13 Кб
Скачать

23. Перегрузка операций

Язык C# позволяет организовать для объектов пользовательского класса или структуры перегрузку операций. Могут быть перегружены унарные операции+,-,!,~,++,--,true,falseи бинарные операции+,-,*,/,%,&,|,^,<<,>>,==,!=,>,<,>=,<=. При перегрузке бинарной операции автоматически перегружается соответствующая операция с присваиванием (например, при перегрузке операции+перегрузится и операция+=). Некоторые операции могут быть перегружены только парами:==и!=,>и<,>=и<=,trueиfalse.

Для перегрузки операций используется специальный статический метод, имя которого образовано из ключевого слова operatorи знака операции. Количество формальных параметров метода зависит от типа операции: унарная операция требует одного параметра, бинарная – двух. Метод обязательно должен иметь модификатор доступаpublic.

Рассмотрим перегрузку операций на примере. Определим класс для представления точек на плоскости с перегруженной операцией сложения:

publicclassPoint

{

publicdoubleX {get;set; }

publicdoubleY {get;set; }

publicoverridestringToString()

{

returnString.Format("X = {0} Y = {1}", X, Y);

}

publicstaticPointoperator+(Pointa,Pointb)

{

// для простоты не делаем проверку аргументов на null

returnnewPoint{X = a.X + b.X, Y = a.Y + b.Y};

}

}

Для объектов класса Pointвозможно использование следующего кода:

varp1 =newPoint{X = 10, Y = 20};

varp2 =newPoint{X = -5, Y = 10};

Console.WriteLine(p1);// печатает "X = 10 Y = 20"

Console.WriteLine(p2);// печатает "X = -5 Y = 10"

Console.WriteLine(p1 + p2);// печатает "X = 5 Y = 30"

Параметры метода перегрузки должны быть параметрами, передаваемыми по значению. Тип формальных параметров и тип возвращаемого значения метода перегрузки обычно совпадает с описываемым типом, хотя это и не обязательное условие. Более того, класс или структура могут содержать версии одной операции с разным типом формальных параметров. Однако не допускается существование двух версий перегрузки операции, различающихся только типом возвращаемого значения. Также класс не может содержать перегруженной операции, у которой ни один из формальных параметров не имеет типа класса.

Дополним класс Point, позволив прибавлять к точке вещественное число:

publicclassPoint

{

. . .

publicstaticPointoperator+(Pointa,doubledelta)

{

returnnewPoint{X = a.X + delta, Y = a.Y + delta};

}

}

Любой класс или структура могут перегрузить операции trueиfalse. Операции перегружаются парой, тип возвращаемого значения операций – булев. Если выполнена подобная перегрузка, объекты могут использоваться как условия в операторах условного перехода и циклов.

Рассмотрим следующий пример. Пусть в классе Pointперегружены операцииtrueиfalse:

publicclassPoint

{

. . .

publicstaticbooloperatortrue(Pointa)

{

return(a.X > 0) || (a.Y > 0);

}

publicstaticbooloperatorfalse(Pointa)

{

// этот метод должен возвращать true,

// если семантика объекта соответствует false

return(a.X == 0) && (a.Y == 0);

}

}

Теперь возможно написать такой код (обратите внимание на оператор if):

varp =newPoint{X = 10, Y = 20};

if(p)

Console.WriteLine("Point is positive");

else

Console.WriteLine("Point has non-positive data");

Если класс или структура Tперегружаютtrue,falseи операции&или|, то становится возможным вычисление булевых выражений по сокращённой схеме. В этом случае:

– выражение x && yтранслируется вT.false(x) ? x : T.&(x,y);

– выражение x || yтранслируется вT.true(x) ? x : T.|(x,y);

Любой класс или структура могут перегрузить операции для неявного и явного приведения типов. При этом используется следующий синтаксис:

publicstaticimplicitoperatorцелевой-тип(приводимый-типимя)

publicstaticexplicitoperatorцелевой-тип(приводимый-типимя)

Ключевое слово implicitиспользуется при перегрузке неявного приведения типов, а ключевое словоexplicit– при перегрузке операции явного приведения. Либоцелевой-тип, либоприводимый-типдолжны совпадать с типом того класса, где выполняется перегрузка операций.

Поместим две перегруженных операции приведения в класс Point:

publicclassPoint

{

. . .

publicstaticimplicitoperatorPoint(doublex)

{

returnnewPoint{X = x};

}

publicstaticexplicitoperatordouble(Pointa)

{

returnMath.Sqrt(a.X * a.X + a.Y * a.Y);

}

}

Вот пример кода, использующего преобразование типов:

varp = newPoint{X = 3, Y = 4};

doubley = 10;

doublex = (double) p;// явное приведение типов

p = y; // неявное приведение типов

Хотелось бы отметить, что разработчик должен ответственно подходить к вопросу перегрузки операций. Методы перегрузки в совокупности с методами приведения типов могут породить код, который трудно сопровождать.