Определение подпрограмм неявного преобразования
Определение подпрограмм неявного преобразования
До этого момента мы с вами создавали пользовательские операции явного преобразования. Но что можно сказать о следующем неявном преобразовании?
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; }
}
}