Г. Шилдт - Полный справочник по C# (1160789), страница 47
Текст из файла (страница 47)
Рассмотрим, например, следующую инструкцию из нашей программы:Глава 9. Перегрузка операторов245if(a |J с) Console.WriteLine("a II с - ИСТИНА.");Сначала к объекту а применяется оператор t r u e . Поскольку в данной ситуацииа — истинный объект, в использовании операторного | -метода необходимости нет.Но эту инструкцию можно переписать и по-другому:I i f ( с | | a) C o n s o l e . W r i t e L i n e ( " с II а - ИСТИНА.");В этом случае оператор t r u e сначала будет применен к объекту с, а он в данной ситуации является ложным. Тогда будет вызван операторный | -метод, чтобы определить,является ли истинным объект а, что здесь как раз соответствует действительности.Хотя на первый взгляд может показаться, что метод, используемый для разрешения использовать операторы сокращенного действия, несколько усложнен, то при более внимательном рассмотрении нетрудно убедиться в его логичности.
Перегружаяоператоры t r u e и f a l s e для класса, вы позволяете компилятору использовать операторы сокращенного действия без их перегрузки в явном виде. Более того, вы получаете возможность применять объекты в условных выражениях. Поэтому, если вам ненужна узкопрофильная реализация операторов "&" или " | ", то лучше всего делать этов полном объеме.Операторы преобразованияИногда объект класса нужно использовать в выражении, включающем другие типыданных.
Такие средства может обеспечить перегрузка одного или нескольких операторов. Но в некоторых случаях желаемого результата можно достичь за счет преобразования типов (из классового в нужный). В целях обработки подобных ситуаций С# позволяет создавать специальный тип операторного метода o p e r a t o r , именуемого оператором преобразования. Такой оператор преобразует объект некоторого класса взначение другого типа.
По сути, оператор преобразования перегружает оператор приведения типов. Операторы преобразования способствуют полной интеграции классовых типов в С#-среду программирования, позволяя объектам класса свободно смешиваться с данными других типов при условии определения операторов преобразованияв эти "другие типы".Существуют две формы операторов преобразования: явная и неявная. В общем виде они записываются так:p u b l i c s t a t i c e x p l i c i t o p e r a t o r тип_результата (ИСХОДНЫЙ__ТИП v) [ r e t u r n значение; ]public s t a t i c implicit operator тип_результата (искодный_тип v) [return значение;]Здесь элемент тип_результата представляет собой тип, в который вы хотите выполнить преобразование; элемент исходный_тип означает тип объекта, подлежащегопреобразованию; элемент v — значение класса после преобразования.
Операторыпреобразования возвращают данные типа тип_результата, причем спецификатортипа здесь указывать не разрешается.Если оператор преобразования определен с ключевым словом i m p l i c i t , преобразование выполняется автоматически, т.е. при использовании объекта в выражении,включающем данные типа тип_резулътата. Если оператор преобразования определен сключевым словом e x p l i c i t , преобразование выполняется при использовании оператора приведения типов. Для одной и той же пары типов, участвующих в преобразовании,нельзя определить как e x p l i c i t - , так и implicit-оператор преобразования.Для иллюстрации определения и использования оператора преобразования создадим его для класса ThreeD.
Предположим, необходимо преобразовать объект типа246Часть I. Язык С#ThreeD в целочисленное значение, чтобы его можно было использовать в выраженияхтипа i n t . Это преобразование будет заключаться в вычислении произведения значений всех трех координат объекта. Для реализации такого преобразования используемimplicit-форму оператора, который будет иметь такой вид:public static implicit operator int(ThreeD opl)return opl.x * opl.у * opl.z;Ниже приведен текст программы, в которой иллюстрируется использование этогооператора преобразования.// Пример использования implicit-оператора преобразования.using System;// Класс трехмерных координат,class ThreeD {int x, у, z; // 3-х-мерные координаты.public ThreeD() { х = у = z = 0; }public ThreeD(int i, int j , int k) {x = i ; у = j ; z = k;}// Перегружаем бинарный оператор "+".public static ThreeD operator +(ThreeD opl, ThreeD op2)ThreeD result = new ThreeD();result.x = opl.x + op2.x;result.у = opl.у + op2.y;result.z = opl.z + op2.z;return result;// Неявное преобразование из типа ThreeD в тип int.public static implicit operator int(ThreeD opl)return opl.x * opl.у * opl.z;// Отображаем координаты X, Y, Z.public void show()Console.WriteLine(x + ", " + у + ", " + z ) ;c l a s s ThreeDDemo {p u b l i c s t a t i c v o i d Main() {,ThreeD a = new T h r e e D ( 1 , 2, 3 ) ;ThreeD b = new ThreeD(10, 10, 1 0 ) ;ThreeD с = new T h r e e D ( ) ;int i;C o n s o l e .
W r i t e ( " К о о р д и н а т ы точки а :a.show();Глава 9. Перегрузка операторов");247Console.WriteLine();Console.Write("Координаты точки b: " ) ;b.show();Console.WriteLine() ;с = a + b; // Суммируем координаты точек а и b.Console.Write("Результат сложения а + b: " ) ;c.show();Console.WriteLine() ;i = a; // Преобразуем в значение типа int.Console.WriteLine("Результат присваивания i = a: " + i) ;Console.WriteLine();i = a * 2 - b ; // Преобразуем в значение типа int.Console.WriteLine("Результат вычисления выражения а * 2 - b: " + i)Привыполнении эта профамма генерирует следующие результаты:Координаты точки а : 1, 2, 3Координаты точки Ь : 10, 10, 10Р е з у л ь т а т сложения а + Ь : 1 1 , 12, 13Результат присваивания i = а: бР е з у л ь т а т вычисления выражения а * 2 - Ь : -988Как видно по результатам выполнения этой профаммы, если объект классаThreeD используется в выражении целочисленного типа (например i = а), к этомуобъекту применяется оператор преобразования.
В данном случае результатом этогопреобразования будет число 6, полученное при умножении всех координат, хранимыхв объекте а. Но если для выражения не требуется преобразование в int-значение,оператор преобразования не вызывается. Поэтому при вычислении выражения с = а+ b операторный метод o p e r a t o r i n t () не вызывается.Можно создавать различные методы преобразования, отвечающие вашим потребностям.
Например, можно определить операторный метод преобразования объектакакого-либо класса в double- или long-значение. При этом каждое преобразованиевыполняется автоматически и независимо от других.Оператор неявного преобразования применяется автоматически в том случае, когда в выражении требуется преобразование, когда методу передается объект, когдавыполняется присваивание, а также когда используется явно заданная операция приведения объекта к результирующему типу. В качестве альтернативного варианта можно создать оператор явного преобразования, который вызывается только в случае явного приведения типов. Оператор явного преобразования не вызывается автоматически.Вот, например, как выглядит предыдущая профамма, переработанная дляиспользования оператора явного преобразования объекта в значение типа i n t :// Использование оператора явного преобразования.using System;// Класс трехмерных координат.248Часть I.
Язык С#class ThreeD {int x, y, z; // 3-х-мерные координаты.public ThreeD() { x = у = z = 0; }public ThreeD(int i, int j, int k) {x = i; у = j; z = k; }// Перегружаем бинарный оператор "+".public static ThreeD operator +(ThreeD opl, ThreeD op2){ThreeD result = new ThreeD();result.x = opl.x + op2.x;result.у = opl.у + op2.y;result.z = opl.z + op2.z;return result;/ / Н а этот раз перегружаем explicit-оператор,public static explicit operator int(ThreeD opl){return opl.x * opl.у * opl.z;// Отображаем координаты X, Y, Z.public void show(){Console.WriteLine(x + ", " + у + ", " + z) ;class ThreeDDemo {public static void Main() {ThreeD a = new ThreeD(1, 2, 3 ) ;ThreeD b = new ThreeD(10, 10, 10);ThreeD с = new ThreeD();int i;Console.Write("Координаты точки а: " ) ;a.show();Console.WriteLine();Console.Write("Координаты точки b: " ) ;b.show();Console.WriteLine() ;с = a + b; // Суммируем координаты объектов а и b.Console.Write("Результат сложения а + b: " ) ;c.
show() ;Console.WriteLine();i = (int) a; // Преобразуем объект в значение// типа int, поскольку явно задана// операция приведения типов.Console.WriteLine("Результат присваивания i = а: " + i ) ;Console.WriteLine();/i = (int)a * 2 - (int)b; // Требуется приведение типов.Глава 9. Перегрузка операторов249Console.WriteLine(" Р е з у л ь т а т вычисления выражения а * 2 - b :ff+ i);Поскольку оператор преобразования теперь определен с использованием ключевого слова e x p l i c i t , преобразование объекта в значение типа i n t должно быть задано как оператор приведения типов.