На этом шаге мы рассмотрим особенности перегрузки таких операторов.
Приведение (преобразование) типов состоит в том, что значение одного типа преобразуется в значение другого типа. Есть два типа преобразования: явное и неявное. При явном преобразовании типа перед значением (преобразуемым к другому типу) в круглых скобках указывается название типа, к которому выполняется преобразование. Неявное преобразование выполняется автоматически в случаях, когда по контексту некоторой команды в определенном месте должно быть значение определенного типа, а по факту указано значение другого типа.
Случаи, когда выполняется неявное преобразование, и правила выполнения явного и неявного преобразований для базовых типов предопределены. Если необходимо выполнять преобразования, в которых исходный тип (значение этого типа преобразуется) или конечный тип (тип, к которому преобразуется значение) относятся к пользовательскому классу, мы можем определить способ такого преобразования, описав в классе соответствующий операторный метод.
Операторные методы, определяющие способ преобразования из пользовательского типа или в пользовательский тип, описываются следующим образом и с учетом таких правил.
Пример, в котором иллюстрируется работа операторных методов для выполнения приведения типов, представлен ниже.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr115_1 { // Класс с перегрузкой операторов приведения типа: class MyClass{ public int code; // Целочисленное поле public char symb; // Символьное поле public String text; // Текстовое поле // Конструктор с тремя аргументами: public MyClass(int n, char s, String t) { code = n; // Значение числового поля symb = s; // Значение символьного поля text = t; // Значение текстового поля } // Переопределение метода ToString(): public override String ToString(){ // Локальная текстовая строка: String txt = "Пoля объекта:\n"; txt += "Числовое поле: " + code + "\n"; txt += "Символьное поле: \'" + symb +"\'\n"; txt += "Teкстовое поле: \"" + text + "\"\n"; txt += "---------------------------"; // Результат метода: return txt; } // Метод для явного приведения к текстовому типу: public static explicit operator String(MyClass obj){ return obj.text;} // Метод для неявного приведения к типу int: public static implicit operator int(MyClass obj){ return obj.code; } // Метод для неявного приведения к типу char: public static implicit operator char(MyClass obj){ return obj.symb; } // Метод для неявного преобразования из типа int: public static implicit operator MyClass(int n){ MyClass t = new MyClass(n, 'B', "Bravo"); return t; } // Метод для явного преобразования из типа char: public static explicit operator MyClass(char s){ return new MyClass(300, s, "Charlie"); } // Метод для неявного преобразования из текстового типа: public static implicit operator MyClass(String t){ return new MyClass(t.Length, t[0], t); } } // Класс с главным методом: class Program { static void Main() { // Создание объектов и проверка результата. // Явное создание объекта: MyClass A = new MyClass(100, 'A', "Alpha"); // Неявно вызывается метод ToString(): Console.WriteLine("Объект А. " + A); // Создание объекта преобразованием из типа int: MyClass B = 200; // Неявно вызывается метод ToString(): Console.WriteLine("Объект В. " + B); // Создание объекта преобразованием из типа char: MyClass C = (MyClass)'C'; // Неявно вызывается метод ToString(): Console.WriteLine("Объект С. " + C); // Создание объекта преобразованием из текста: MyClass D = "Delta"; // Неявно вызывается метод ToString(): Console.WriteLine("Объект D. " + D); Console.WriteLine("Еще раз поля объекта А:"); // Явное преобразование в тип int: Console.WriteLine("Число: " + (int)A); // Явное преобразование в тип char: Console.WriteLine("Символ: " + (char)A); // Явное преобразование в текст: Console.WriteLine("Текст: " + (String)A + "\n"); Console.WriteLine("Разные операции:"); // Целочисленная переменная: int n; // Неявное преобразование к типу int: n = A + B; Console.WriteLine("Значение А + В = " + n); // Неявное преобразование к типу char: char s = B; Console.WriteLine("Символ: " + s); // Последовательное преобразование из текстового // типа к типу MyClass, а затем к типу int: Console.WriteLine("Число: " + (int)(MyClass)"Echo"); // Задержка: Console.ReadLine(); } } }
При выполнении программы получаем такой результат.
Рис.1. Результат выполнения программы
Проанализируем программный код и результат его выполнения. Мы имеем дело с классом MyClass с тремя полями (целочисленным, символьным и текстовым). У класса есть конструктор с тремя аргументами, в классе переопределен метод ToString(), а еще там описано несколько операторных методов для выполнения приведения типов. Мы определяем такие способы приведения типов:
explicit operator String(MyClass obj)
implicit operator int(MyClass obj)
implicit operator char(MyClass obj)
implicit operator MyClass(int n)
MyClass t = new MyClass(n, 'B', "Bravo");
explicit operator MyClass(char s)
new MyClass(300, s, "Charlie") .
implicit operator MyClass(String t)
new MyClass(t.Length, t[0], t) .
В главном методе программы проверяется работа операторных методов для выполнения явного и неявного приведения типов. Объект А создается обычным способом, с вызовом конструктора. Еще три объекта (В, С и D) создаются с использованием операторов приведения типа. Так, при выполнении команды
MyClass B = 200; ,
MyClass C = (MyClass)'C'; ,
Если в команде
MyClass C = (MyClass)'C';
MyClass C = 'C';
MyClass C = 'C';
Еще один объект создан командой
MyClass D = "Delta"; .
В классе MyClass описан метод ToString() и оператор явного приведения к текстовому типу. Результат у них разный. При выполнении команд вида
"Объект А. " + A,
Инструкции (int)A и (char)А являются примером явного преобразования объекта класса MyClass в значение типа int и значение типа char соответственно. А вот когда выполняется команда
n = A + B; ,
char s = B; .
Еще одна инструкция, достойная внимания, имеет вид
(int)(MyClass)"Echo" .
На следующем шаге мы рассмотрим особенности перегрузки команд присваивания.