Несмотря на всю полезность неявных преобразований типов, они неспособны удовлетворить все потребности в программировании, поскольку допускают лишь расширяющие преобразования совместимых типов. А во всех остальных случаях приходится обращаться к приведению типов.
Приведение — это команда компилятору преобразовать результат вычисления выражения в указанный тип.
А для этого требуется явное преобразование типов. Ниже приведена общая форма приведения типов.
(целевой_тип) выражение
Здесь целевой_тип
обозначает тот тип, в который желательно преобразовать указанное выражение. Рассмотрим для примера следующее объявление переменных.
double x, y;
Если результат вычисления выражения x/y
должен быть типа int
, то следует записать следующее.
(int) (x / y)
Несмотря на то, что переменные x
и y
относятся к типу double
, результат вычисления выражения x/y
преобразуется в тип int
благодаря приведению. В данном примере выражение x/y
следует непременно указывать в скобках, иначе приведение к типу int
будет распространяться только на переменную x
, а не на результат ее деления на переменную y
. Приведение типов в данном случае требуется потому, что неявное преобразование типа double
в тип int
невозможно.
Если приведение типов приводит к сужающему преобразованию, то часть информации может быть потеряна. Например, в результате приведения типа long
к типу int
часть информации потеряется, если значение типа long
окажется больше диапазона представления чисел для типа int
, поскольку старшие разряды этого числового значения отбрасываются. Когда же значение с плавающей точкой приводится к целочисленному, то в результате усечения теряется дробная часть этого числового значения. Так, если присвоить значение 1,23 целочисленной переменной, то в результате в ней останется лишь целая часть исходного числа (1), а дробная его часть (0,23) будет потеряна.
В следующем примере программы демонстрируется ряд преобразований типов, требующих приведения. В этом примере показан также ряд ситуаций, в которых приведение типов становится причиной потери данных.
// Продемонстрировать приведение типов.
using System;
class CastDemo {
static void Main() {
double x, y;
byte b;
int i;
char ch;
uint u;
short s;
long l;
x = 10.0;
y = 3.0;
// Приведение типа double к типу int, дробная часть числа теряется,
i = (int)(x / y);
Console.WriteLine("Целочисленный результат деления х / y: " + i);
Console.WriteLine();
// Приведение типа int к типу byte без потери данных.
i = 255;
b = (byte)i;
Console.WriteLine("b после присваивания 255: " + b +
" -- без потери данных.");
// Приведение типа int к типу byte с потерей данных.
i = 257;
b = (byte)i;
Console.WriteLine("b после присваивания 257: " + b +
" -- с потерей данных.");
Console.WriteLine();
// Приведение типа uint к типу short без потери данных.
u = 32000;
s = (short)u;
Console.WriteLine("s после присваивания 32000: " +
s + " — без потери данных.");
// Приведение типа uint к типу short с потерей данных,
u = 64000;
s = (short)u;
Console.WriteLine("s после присваивания 64000: " +
s + " -- с потерей данных.");
Console.WriteLine();
// Приведение типа long к типу uint без потери данных.
l = 64000;
u = (uint)l;
Console.WriteLine("и после присваивания 64000: " + u +
" -- без потери данных. ");
// Приведение типа long к типу uint с потерей данных.
l = -12;
u = (uint)l;
Console.WriteLine("u после присваивания -12: " + u +
" -- с потерей данных.");
Console.WriteLine();
// Приведение типа `int` к типу char,
b = 88; // код ASCII символа X
ch = (char)b;
Console.WriteLine("ch после присваивания 88: " + ch);
}
}
Вот какой результат дает выполнение этой программы.
Целочисленный результат деления x / y: 3
b после присваивания 255: 255 -- без потери данных.
b после присваивания 257: 1 — с потерей данных.
s после присваивания 32000: 32000 -- без потери данных,
s после присваивания 64000: -1536 -- с потерей данных.
u после присваивания 64000: 64000 — без потери данных,
u после присваивания -12: 4294967284 -- с потерей данных
сh после присваивания 88: X
Рассмотрим каждую операцию присваивания в представленном выше примере программы по отдельности. Вследствие приведения результата деления x/y
к типу int
отбрасывается дробная часть числа, а следовательно, теряется часть информации.
Когда переменной b
присваивается значение 255, то информация не теряется, поскольку это значение входит в диапазон представления чисел для типа byte
. Но когда переменной b
присваивается значение 257, то часть информации теряется, поскольку это значение превышает диапазон представления чисел для типа byte
. Приведение типов требуется в обоих случаях, поскольку неявное преобразование типа int
в тип byte
невозможно.
Когда переменной s
типа short
присваивается значение 32 000 переменной u
типа uint
, потери данных не происходит, поскольку это значение входит в диапазон представления чисел для типа short
. Но в следующей операции присваивания переменная u
имеет значение 64 000, которое оказывается вне диапазона представления чисел для типа short
, и поэтому данные теряются. Приведение типов требуется в обоих случаях, поскольку неявное преобразование типа uint
в тип short
невозможно.
Далее переменной u
присваивается значение 64 000 переменной 1
типа long
. В этом случае данные не теряются, поскольку значение 64 000 оказывается вне диапазона представления чисел для типа uint
. Но когда переменной u
присваивается значение -12
, данные теряются, поскольку отрицательные числа также оказываются вне диапазона представления чисел для типа uint
. Приведение типов требуется в обоих случаях, так как неявное преобразование типа long
в тип uint
невозможно.
И наконец, когда переменной char
присваивается значение типа byte
, информация не теряется, но приведение типов все же требуется.
Автоматическое преобразование типов | Преобразование типов в выражениях |