Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

{

for (int j = 0; j < Length; j++)

{

Console.Write("*");

}

Console.WriteLine;

}

}

public override string ToString => $"[Length = {Length}]";

// Rectangle можно явно преобразовывать в Square.

public static explicit operator Square(Rectangle r)

{

Square s = new Square {Length = r.Height};

return s;

}

}

}

Обратите

внимание, что в текущей версии типа
Square
определена явная операция преобразования. Подобно перегрузке операций процедуры преобразования используют ключевое слово operator в сочетании с ключевым словом
explicit
или
implicit
и должны быть определены как
static
. Входным параметром является сущность, из которой выполняется преобразование, а типом операции — сущность, в которую производится преобразование.

В данном случае предположение заключается в том, что квадрат (будучи геометрической фигурой с четырьмя сторонами равной длины) может быть получен из высоты прямоугольника. Таким образом, вот как преобразовать

Rectangle
в
Square
:

using System;

using CustomConversions;

Console.WriteLine("***** Fun with Conversions *****\n");

// Создать экземпляр Rectangle.

Rectangle r = new Rectangle(15, 4);

Console.WriteLine(r.ToString);

r.Draw;

Console.WriteLine;

// Преобразовать r в Square на основе высоты Rectangle
.

Square s = (Square)r;

Console.WriteLine(s.ToString);

s.Draw;

Console.ReadLine;

Ниже показан вывод:

***** Fun with Conversions *****

[Width = 15; Height = 4]

***************

***************

***************

***************

[Length = 4]

****

****

****

****

Хотя преобразование

Rectangle
в
Square
в пределах той же самой области действия может быть не особенно полезным, взгляните на следующий метод, который спроектирован для приема параметров типа
Square
:

// Этот метод требует параметр типа Square.

static void DrawSquare(Square sq)

{

Console.WriteLine(sq.ToString);

sq.Draw;

}

Благодаря наличию операции явного преобразования в типе

Square
методу
DrawSquare
на обработку можно передавать типы
Rectangle
, применяя явное приведение:

...

// Преобразовать Rectangle в Square для вызова метода.

Rectangle rect = new Rectangle(10, 5);

DrawSquare((Square)rect);

Console.ReadLine;

Дополнительные

явные преобразования для типа Square

Теперь, когда экземпляры

Rectangle
можно явно преобразовывать в экземпляры
Square
, давайте рассмотрим несколько дополнительных явных преобразований. Учитывая, что квадрат симметричен по всем сторонам, полезно предусмотреть процедуру преобразования, которая позволит вызывающему коду привести целочисленный тип к типу
Square
(который, естественно, будет иметь длину стороны, равную переданному целочисленному значению). А что если вы захотите модифицировать еще и
Square
так, чтобы вызывающий код мог выполнять приведение из
Square
в
int
? Вот как выглядит логика вызова:

...

// Преобразование int в Square.

Square sq2 = (Square)90;

Console.WriteLine("sq2 = {0}", sq2);

// Преобразование Square в int.

int side = (int)sq2;

Console.WriteLine("Side length of sq2 = {0}", side);

Console.ReadLine;

Ниже показаны изменения, внесенные в структуру

Square
:

public struct Square

{

...

public static explicit operator Square(int sideLength)

{

Square newSq = new Square {Length = sideLength};

return newSq;

}

public static explicit operator int (Square s) => s.Length;

}

По правде говоря, преобразование

Square
в
int
может показаться не слишком интуитивно понятной (или полезной) операцией (скорее всего, вы просто будете передавать нужные значения конструктору). Тем не менее, оно указывает на важный факт, касающийся процедур специальных преобразований: компилятор не беспокоится о том, из чего и во что происходит преобразование, до тех пор, пока вы пишете синтаксически корректный код.

Таким образом, как и с перегрузкой операций, возможность создания операции явного приведения для заданного типа вовсе не означает необходимость ее создания. Обычно этот прием будет наиболее полезным при создании типов структур, учитывая, что они не могут принимать участие в классическом наследовании (где приведение обеспечивается автоматически).

Определение процедур неявного преобразования

До сих пор мы создавали различные специальные операции явного преобразования. Но что насчет следующего неявного преобразования?

...

Square s3 = new Square {Length = 83};

// Попытка сделать неявное приведение?

Rectangle rect2 = s3;

Console.ReadLine;

Данный код не скомпилируется, т.к. вы не предоставили процедуру неявного преобразования для типа

Rectangle
. Ловушка здесь вот в чем: определять одновременно функции явного и неявного преобразования не разрешено, если они не различаются по типу возвращаемого значения или по списку параметров. Это может показаться ограничением; однако вторая ловушка связана с тем, что когда тип определяет процедуру неявного преобразования, то вызывающий код вполне законно может использовать синтаксис явного приведения!

Поделиться с друзьями: