Оператори перетворення
Іноді об'єкт певного класу потрібно використовувати у виразі, що включає дані інших типів. В одних випадках для цієї мети виявляється
Глава 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 або з цього класу.
• Для тих самих вихідних і цільових типів даних не можна вказувати одночасне явне і неявне перетворення.