Оператори перетворення

Іноді об'єкт певного класу потрібно використовувати у виразі, що включає дані інших типів. В одних випадках для цієї мети виявляється

Глава 9. Перевантаження операторів 293

придатне перевантаження одного або більше операторів, а в інших випадках - звичайне перетворення типу класу в цільовий тип. Для подібних ситуацій в C# передбачено особливий різновид операторного способу, звана оператором перетворення. Такий оператор перетворює об'єкт вихідного класу на інший тип. Оператори перетворення допомагають повністю інтегрувати типи класів у середовище програмування на С#, дозволяючи вільно користуватися класами разом з іншими типами даних, за умови, що визначено порядок перетворення на ці типи.

Існують дві форми операторів перетворення: явна та неявна. Нижче вони представлені у загальному вигляді:

public static explicit operator цільовий_тип(вихідний_тип v)

public static implicit operator цільовий_тип(вихідний_тип v)

де цільовий_тип позначає той тип, який виконується перетворення; вихідний_тип - той тип, який перетворюється; значення - конкретне значення, що набуває класом після перетворення. Оператори перетворення повертають дані, що мають цільовий_тип, причому вказувати інші типи даних, що повертаються, не дозволяється.

Якщо оператор перетворення вказаний у неявній формі (implicit), то перетворення викликається автоматично, наприклад, у тому випадку, коли об'єкт використовується у виразі разом із значенням цільового типу. Якщо оператор перетворення вказаний у явній формі ( explicit ), то перетворення викликається у тому випадку, коли виконується приведення типів. Для тих самих вихідних і цільових типів даних не можна вказувати операторперетворення одночасно у явній та неявній формі.

Створимо оператор перетворення спеціально для класу ThreeD, щоб продемонструвати його застосування. Припустимо, що потрібно перетворити об'єкт типу ThreeD на ціле значення, щоб потім використовувати його в цілісному вираженні. Таке перетворення потрібно, зокрема, щоб одержати твори всіх трьох координат об'єкта. З цією метою ми скористаємося наступною неявною формою оператора перетворення.

public static implicit operator int(ThreeD op1)

return op1.x*op1.y*op1.z;

Нижче наведено приклад програми, що демонструє застосування цього оператора перетворення.

/ / Приклад застосування оператора неявного перетворення.

// Клас зберігання тривимірних координат.

int х, у, z; // Тривимірні координати

public ThreeD(int i, int j, int k)

// Перевантажити бінарний оператор +.

public static ThreeD operator + (ThreeD op1, ThreeD op2)

294 Частина I. Мова С#

ThreeD result = new ThreeD);

result.x = op1.x + op2.x; result.у = op1.у + op2.y; result.z = op1.z + op2.z;

// Неявне перетворення об'єкта типу ThreeD типу int. public static implicit operator int(ThreeD op1)

return op1.x * op1. у * op1.z;

// Вивести координати X, Y, Z. public void Show()

Console.WriteLine(x + ", " + у + ", " + z);

ThreeD a = new ThreeD(1, 2, 3); ThreeD b = New ThreeD (10, 10, 10); ThreeD = New ThreeD();

Console.Write("Координати точки a:"); a.Show();

Console.WriteLine(); Console.Write("Координати точки b:"); b.Show();

с = a + b; // Скласти координати точок а і b Console.Write ("Результат додавання a + b:"); c.Show();

i = a; // Перетворити на тип intConsole.WriteLine("Результат присвоєння i = a:" + i); Console.WriteLine();

i = a * 2 - b; // Перетворити на тип int Console.WriteLine("Результат обчислення виразу a * 2 - b: " + i

Ось який результат призводить виконання цієї програми.

Координати точки а: 1, 2, 3

Координати точки b: 10, 10, 10

Глава 9. Перевантаження операторів 295

Результат додавання а + b: 11, 12, 13

Результат присвоєння i = а: 6

Результат обчислення виразу а*2 - b: -988

Як випливає з наведеного вище прикладу програми, коли об'єкт типу ThreeD використовується в такому цілісному вираженні, як i = а відбувається його перетворення. У цьому конкретному випадку перетворення призводить до повернення цілого значення 6, яке є добутком координат точки а, що зберігаються в об'єкті тієї ж назви. Але якщо для обчислення виразу перетворення в тип int не потрібно, оператор перетворення не викликається. Саме тому операторний метод operator int() не викликається при обчисленні виразу = а + b .

Для різних цілей можна створити різні оператори перетворення. Так, для перетворення об'єкта типу ThreeD на тип double можна було б визначити другий оператор перетворення. При цьому кожен вид перетворення виконувався б автоматично та незалежно від іншого.

Оператор неявного перетворення застосовується автоматично в таких випадках: коли у виразі потрібно перетворення типів; методом передається об'єкт; здійснюється привласнення та проводиться явне приведення до цільового типу. З іншого боку, можна створити оператор явного перетворення, що викликається лише тоді, коли відбувається явне наведення типів. У такому разі оператор явного перетворення не викликаєтьсяавтоматично. Як приклад нижче наведено варіант попередньої програми, перероблений для демонстрації явного перетворення в тип int.

// Застосувати явне перетворення.

// Клас зберігання тривимірних координат. class ThreeD

int х, у, z; // Тривимірні координати public ThreeD()

public ThreeD(int i, int j, int k)

// Перевантажити бінарний оператор +.

public static ThreeD operator + (ThreeD op1, ThreeD op2)

ThreeD result = New ThreeD();

result.x = op1.x + op2.x; result.у = op1.y + op2.y; result.z = op1.z + op2.z;

// Виконати цього разу явне перетворення типів. public static explicit operator int(ThreeD op1)

return op1.x*op1.y*op1.z;

296 Частина I. Мова С#

// Вивести координати X, Y, Z. public void Show()

Console.WriteLine(x + ", " + у + ", " + z);

ThreeD a = new ThreeD(1, 2, 3); ThreeD b = New ThreeD (10, 10, 10); ThreeD = New ThreeD();

Console.Write("Координати точки a:"); a.Show();

Console.WriteLine(); Console.Write("Координати точки b:"); b.Show();

с = a + b; // Скласти координати точок а і b Console.Write ("Результат додавання a + b:"); c.Show();

i = (int) a; // Перетворити на тип int явно,

// оскільки вказано наведення типів

Console.WriteLine("Результат присвоєння i = а:" + i); Console.WriteLine();

i = (int) a * 2 - (int) b; // явно потрібне приведення типів

Console.WriteLine("Результат обчислення виразу а * 2 - b:" + i);

Оператор перетворення тепер зазначений у явній формі, і тому перетворення має бути явно наведено до типу int. Наприклад, наступний рядок коду не буде скомпілюваний, якщо виключити наведення типів.

i = (int) а; //перетворити на тип int явно,

// оскільки вказано наведення типів

На оператори перетворення накладається низка таких обмежень.

• Вихідний або цільовий тип перетворення повинен відноситися до класу, для якого оголошено це перетворення. Зокрема, не можна перевизначити перетворення на тип int , якщо воно спочатку вказано як перетворення на тип double .

• Не можна вказувати перетворення на клас object або з цього класу.

• Для тих самих вихідних і цільових типів даних не можна вказувати одночасне явне і неявне перетворення.