Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Определение подпрограмм неявного преобразования
Определение подпрограмм неявного преобразования
До этого момента мы с вами создавали пользовательские операции явного преобразования. Но что можно сказать о следующем неявном преобразовании?
static void Main(string[] args) {
…
// Попытка выполнить неявное преобразование?
Square s3;
s3.Length = 83;
Rectangle rect2 = s3;
}
Как вы можете догадаться сами, этот программный код скомпилирован не будет, поскольку в нем не предлагается никакой подпрограммы неявного преобразования для типа Rectangle. Тут нас подстерегает "ловушка": в одном и том же типе нельзя определять явные и неявные функции преобразования, не отличающиеся по типу возвращаемого значения или по набору параметров. Может показаться, что это правило является слишком ограничивающим, но не следует забывать о том, что даже если тип определяет подпрограмму неявного преобразования, вызывающая сторона "имеет право" использовать синтаксис явного преобразования!
Запутались? Чтобы прояснить ситуацию, добавим в структуру Rectangle подпрограмму неявного преобразования, используя ключевое слово C# implicit (в следующем программном коде предполагается, что ширина результирующего Rectangle получается с помощью умножения стороны Square на 2).
public struct Rесtangle {
…
public static implicit operator Rectangle(Square s) {
Rectangle r;
r.Height = s.Length;
// Ширина нового прямоугольника равна
// удвоенной длине стороны квадрата.
r.Width = s.Length * 2;
}
}
С такими изменениями вы получаете возможность преобразовывать указанные типы так.
static void Main(string[] args) {
…
// Неявное преобразование: все OK!
Square s3;
s3.Length = 83;
Rectangle rect2 = s3;
Console.WriteLine("rect2 = {0}", rect2);
DrawSquare(s3);
// Синтаксис явного преобразования: тоже OK!
Square s4;
S4.Length = 3;
Rectangle rect3 = (Rectangle)s4;
Console.WriteLine("rect3 = {0}", rect3);
…
}
Снова подчеркнем, что допускается определение подпрограмм и явного, и неявного преобразования для одного и того же типа, но только если отличаются их сигнатуры. Поэтому мы можем обновить Square так, как показано ниже.
public struct Square {
…
// Можно вызывать как Square sq2 = (Square)90;
// или как Square sq2 = 90;
public static implicit operator Square(int sideLength) {
Square newSq;
newSq.Length = sideLength;
return newSq;
// Должно вызываться как int side = (Square)mySquare;
public static explicit operator int(Square s) { return s.Length; }
}
}
- Создание пользовательских индексаторов
- Внутреннее представление индексаторов типов
- Заключительные замечания об индексаторах
- Перегрузка операций
- Перегрузка бинарных операций
- Перегрузка унарных операций
- Перегрузка операций проверки на тождественность
- Перегрузка операций сравнения
- Внутреннее представление перегруженных операций
- Использование перегруженных операций в языках, не поддерживающих перегрузку операций
- Заключительные замечания о перегрузке операций
- Пользовательские преобразования типов
- Создание пользовательских подпрограмм преобразования
- Определение подпрограмм неявного преобразования
- Внутреннее представление пользовательских подпрограмм преобразования
- Ключевые слова C#, предназначенные для более сложных конструкций
- Директивы препроцессора C#
- Резюме
- Внутреннее представление пользовательских подпрограмм преобразования
- Пользовательские преобразования типов
- 1.2. Определение количества информации. Единицы измерения количества информации
- Определение версии клиента
- Определение пользовательского формата числовых данных
- Определение целей. Построение цепочек
- Определение необходимого системного вызова
- Раздел 1 Лояльность: определение и ключевые факторы
- Определение позиционного уровня
- 3.3. Определение объектов защиты
- 2.7 Преобразования типов
- Определение собственной миссии