KnigaRead.com/
KnigaRead.com » Разная литература » Прочее » Герберт Шилдт - C# 4.0 полное руководство - 2011

Герберт Шилдт - C# 4.0 полное руководство - 2011

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Герберт Шилдт - C# 4.0 полное руководство - 2011". Жанр: Прочее издательство неизвестно, год неизвестен.
Перейти на страницу:

где целевой_тип обозначает тот тип, в который выполняется преобразование; ис-ходный_тип — тот тип, который преобразуется; значение — конкретное значение, приобретаемое классом после преобразования. Операторы преобразования возвращают данные, имеющие целевой_тип, причем указывать другие возвращаемые типы данных не разрешается.

Если оператор преобразования указан в неявной форме (implicit), то преобразование вызывается автоматически, например, в том случае, когда объект используется в выражении вместе со значением целевого типа. Если же оператор преобразования указан в явной форме (explicit), то преобразование вызывается в том случае, когда выполняется приведение типов. Для одних и тех же исходных и целевых типов данных нельзя указывать оператор преобразования одновременно в явной и неявной форме.

Создадим оператор преобразования специально для класса ThreeD, чтобы продемонстрировать его применение. Допустим, что требуется преобразовать объект типа ThreeD в целое значение, чтобы затем использовать его в целочисленном выражении. Такое преобразование требуется, в частности, для получения произведения всех трех координат объекта. С этой целью мы воспользуемся следующей неявной формой оператора преобразования.

public static implicit operator int(ThreeD opl)

{

return opl.x * opl.у * opl.z;

}

Ниже приведен пример программы, демонстрирующей применение этого оператора преобразования.

// Пример применения оператора неявного преобразования, using System;

// Класс для хранения трехмерных координат, class ThreeD {

int х, у, z; // трехмерные координаты

public ThreeD()    {    х = у = z = 0;    }

public ThreeD(int i, int j, int k) { x = i; у = j; z = k; }

// Перегрузить бинарный оператор +.

public static ThreeD operator +(ThreeD opl, ThreeD op2)

{

ThreeD result = new ThreeD();

result.x    =    opl.x    +    op2.x;

result.у    =    opl.y    +    op2.y;

result.z    =    opl.z    +    op2.z;

return result;

}

// Неявное преобразование объекта типа ThreeD к типу int. public static implicit operator int(ThreeD opl)

{

return opl.x * opl.y * opl.z;

}

// Вывести координаты X, Y, Z. public void Show()

{

Console.WriteLine(x + ", " + у + ",    "    +    z)    ;

}

}

class ThreeDDemo { static void Main() {

ThreeD a = new ThreeD(1, 2, 3);

ThreeD b = new ThreeD(10, 10, 10);

ThreeD с = new ThreeD(); int i;

Console.Write("Координаты точки a: ");

a.Show();

Console.WriteLine() ;

Console.Write("Координаты точки b: ");

b.Show();

Console.WriteLine();

с = a + b; // сложить координаты точек а и b Console.Write("Результат сложения a + b: ");

c.Show    ();

Console.WriteLine(); i = a; // преобразовать в тип int

Console.WriteLine("Результат присваивания i = a: " + i) ; Console.WriteLine();

i=a*2-b; // преобразовать в тип int

Console.WriteLine("Результат вычисления выражения a * 2 -

}

}

Вот к какому результату приводит выполнение этой программы.

Координаты точки а: 1, 2, 3

Координаты точки Ь: 10, 10, 10

Результат сложения а+Ь: 11, 12, 13 Результат присваивания i = а: 6

Результат вычисления выражения а * 2 - Ь: -988

Как следует из приведенного выше примера программы, когда объект типа ThreeD используется в таком целочисленном выражении, как i = а, происходит его преобразование. В этом конкретном случае преобразование приводит к возврату целого значения 6, которое является произведением координат точки а, хранящихся в объекте того же названия. Но если для вычисления выражения преобразование в тип int не требуется, то оператор преобразования не вызывается. Именно поэтому операторный метод operator int () не вызывается при вычислении выражения с = а + Ь.

Но для различных целей можно создать разные операторы преобразования. Так, для преобразования объекта типа ThreeD в тип double можно было бы определить второй оператор преобразования. При этом каждый вид преобразования выполнялся бы автоматически и независимо от другого.

Оператор неявного преобразования применяется автоматически в следующих случаях: когда в выражении требуется преобразование типов; методу передается объект; осуществляется присваивание и производится явное приведение к целевому типу. С другой стороны, можно создать оператор явного преобразования, вызываемый только тогда, когда производится явное приведение типов. В таком случае оператор явного преобразования не вызывается автоматически. В качестве примера ниже приведен вариант предыдущей программы, переделанный для демонстрации явного преобразования в тип int.

// Применить явное преобразование, using System;

// Класс для хранения трехмерных координат, class ThreeD {

int х, у, z; // трехмерные координаты public ThreeD()    {    х    = у = z = 0; }

public ThreeD(int i, int j, int k) { x = i; у = j; z = k; }

// Перегрузить бинарный оператор +.

public static ThreeD operator +(ThreeD opl, ThreeD op2)

{

ThreeD result = new ThreeD();

result.x = opl.x + op2.x; result.у = opl.у + op2.y; result.z = opl.z + op2.z;

return result;

}

// Выполнить на этот раз явное преобразование типов, public static explicit operator int(ThreeD opl)

{

return opl.x * opl.у * opl.z;

}

// Вывести координаты X, Y, Z. public void Show ()

{

Console.WriteLine(x + ",    "    +    у    +    ",    "    +    z)    ;

}

}

class ThreeDDemo { static void Main() {

ThreeD a = new ThreeD(1, 2, 3) ;

ThreeD b = new ThreeD(10, 10, 10);

ThreeD с = new ThreeD(); int i;

Console.Write("Координаты точки a: ");

a.Show();

Console.WriteLine() ;

Console.Write("Координаты точки b: ");

b.Show()    ;

Console.WriteLine() ;

с = a + b; // сложить координаты точек а и b Console.Write("Результат сложения a + b: ");

c.Show();

Console.WriteLine() ;

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.

•    Нельзя указывать преобразование в класс ob j ect или же из этого класса.

•    Для одних и тех же исходных и целевых типов данных нельзя указывать одновременно явное и неявное преобразование.

•    Нельзя указывать преобразование базового класса в производный класс. (Подробнее о базовых и производных классах речь пойдет в главе 11.)

•    Нельзя указывать преобразование в интерфейс или же из него. (Подробнее об интерфейсах — в главе 12.)

Помимо указанных выше ограничений, имеется ряд рекомендаций, которыми обычно руководствуются при выборе операторов явного или неявного преобразования. Несмотря на все преимущества неявных преобразований, к ним следует прибегать только в тех случаях, когда преобразованию не свойственны ошибки. Во избежание подобных ошибок неявные преобразования должны быть организованы только в том случае, если удовлетворяются следующие условия. Во-первых, информация не теряется, например, в результате усечения, переполнения или потери знака. И во-вторых, преобразование не приводит к исключительной ситуации. Если же неявное преобразование не удовлетворяет этим двум условиям, то следует выбрать явное преобразование.

Рекомендации и ограничения по перегрузке операторов

Действие перегружаемого оператора распространяется на класс, для которого он определяется, и никак не связано с его первоначальным применением к данным встроенных в C# типов. Но ради сохранения ясности структуры и удобочитаемости исходного кода перегружаемый оператор должен, по возможности, отражать основную суть своего первоначального назначения. Например, назначение оператора + для класса ThreeD по сути не должно заметно отличаться от его назначения для целочисленных типов данных. Если бы, например, определить оператор + относительно некоторого класса таким образом, чтобы по своему действию он стал больше похожим на оператор /, то вряд ли от этого было бы много проку. Главный принцип перегрузки операторов заключается в следующем: несмотря на то, что перегружаемый оператор может получить любое назначение, ради ясности новое его назначение должно быть так или иначе связано с его первоначальным назначением.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*