Материал предоставлен https://it.rfei.ru

Приведение несовместимых типов

Несмотря на всю полезность неявных преобразований типов, они неспособны удовлетворить все потребности в программировании, поскольку допускают лишь расширяющие преобразования совместимых типов. А во всех остальных случаях приходится обращаться к приведению типов.

Приведение — это команда компилятору преобразовать результат вычисления выражения в указанный тип.

А для этого требуется явное преобразование типов. Ниже приведена общая форма приведения типов.

(целевой_тип) выражение

Здесь целевой_тип обозначает тот тип, в который желательно преобразовать указанное выражение. Рассмотрим для примера следующее объявление переменных.

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, информация не теряется, но приведение типов все же требуется.

Автоматическое преобразование типовПреобразование типов в выражениях