Преобразование базовых типов данных

При рассмотрении арифметических операторов нам пришлось немного забежать вперед и узнать, что в C# производится некое преобразование типов данных. О том, что из себя представляет преобразование типов и как оно работает мы и поговорим в этой части.

Итак, на данный момент, мы уже знаем, что C# является типизированным языком программирования и каждая переменная в нашей программе должна иметь имя и тип. При этом, мы не можем изменять тип переменной или присваивать ей значение другого типа. Например,

int i = 10;

//Ошибка CS0128 Локальная переменная или функция с именем "i" уже определена в этой области.
string i = "строка"; //попытались изменить тип переменной

Если вы работаете в Visual Studio, то сразу увидите ошибку так как в коде выше мы попытались заново определить переменную с именем i, но другим типом данных. Следующий код также приведет к ошибке:

int i;
//Ошибка CS0029 Не удается неявно преобразовать тип "string" в "int"
i = "строка";

При этом, красной волнистой линией в Visual Studio будет подчеркнуто новое значение, которое мы пытаемся присвоить переменной. Именно в этом примере (точнее в тексте ошибки) мы и подходим к сегодняшней теме — преобразование типов данных.

В C# преобразования типов данных условно можно разделить на два вида — это неявные преобразования и явные преобразования. В чём их суть — разберемся далее.

Неявные преобразования

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

byte a = 255;
int b = a;
a = b;

в первой строке мы инициализировали переменную типа byte. Как мы уже знаем, этот тип данных может принимать значения от 0 до 255. Далее мы пытаемся присвоить значение переменной a новой переменной b у которой определен тип int. Вот в этой строке и будет происходить неявное преобразование. Так как переменная типа int может принимать значения от -2 147 483 648 до 2 147 483 647, то значение типа byte явно входит в этот диапазон, поэтому производится неявное преобразование из меньшего (byte) в больший (int) целочисленный тип данных без какой-либо потери данных. Также, такое преобразование называется расширяющим — мы расширяем размер объекта в памяти.

А вот на третьей строке кода мы пытаемся произвести обратную операцию — присвоить переменной a значение переменной b:

a = b;

и мы получим ошибку преобразования так как мы пытаемся переменной типа byte присвоить значение типа int и здесь уже неявное преобразование не срабатывает так как это может привести к потере данных. Рассмотрим другой пример, который демонстрирует ошибку преобразования данных:

byte a = 10;
a = a + 100;

Этот пример не столь очевидный, как предыдущий так как, на первый взгляд может показаться, что всё в порядке — переменная типа byte сразу после инициализации имеет значение 10 и во второй строке мы пытаемся прибавить к этому значению ещё 100, то есть получить число 110, которое точно входит в диапазон byte (0 — 255). Однако, Visual Studio также выдаст нам ошибку следующего вида:

CS0266 Не удается неявно преобразовать тип «int» в «byte». Существует явное преобразование (возможно, пропущено приведение типов).

Всё дело в том, что мы пытаемся выполнить сложение двух чисел и в C# результатом сложения двух целых чисел по умолчанию выступает тип int. А так как тип int имеет более широкий диапазон значений, чем byte (тип данных для переменной), то Visual Studio вполне справедливо выдает нам ошибку. С тем, как мы можем исправить такие ошибки мы разберемся чуть ниже. А пока стоит представить небольшую таблицу, демонстрирующую то из какого типа в какие типы может производиться неявное преобразование числовых данных:

Тип В какие типы данных может неявно преобразовываться
sbyte shortintlongfloatdoubledecimal или nint
byte shortushortintuintlongulongfloatdoubledecimalnint или nuint
short intlongfloatdouble или decimal либо nint
ushort intuintlongulongfloatdouble или decimalnint или nuint
int longfloatdouble или decimalnint
uint longulongfloatdouble или decimal либо nuint
long floatdouble или decimal
ulong floatdouble или decimal
float double
nint longfloatdouble или decimal
nuint ulongfloatdouble или decimal

 

Здесь стоит обратить внимание на то, что любой целочисленный тип данных свободно преобразуется в вещественный. Например, int в double или byte в float и так далее. При этом не поддерживается неявное преобразования:

  • в типы byte и sbyte.
  • из типов double и decimal.
  • между типом decimal и типами float или double.

Явные преобразования

Явные преобразования также называют приведением типов. Для явных преобразований требуется выражение приведения. Приведение требуется, если в ходе преобразования данные могут быть утрачены или преобразование может завершиться сбоем по другим причинам. Типичными примерами являются числовое преобразование в тип с меньшей точностью или меньшим диапазоном допустимых значений. То есть, в случае явного преобразования мы берем на себя все возможные риски, связанные с потерей данных и возможными сбоями в работе приложения.

Опять же, вернемся к нашему последнему примеру с типами int и byte.

byte a = 10; 
a = a + 100;

Здесь у нас нет никакого риска потери данных и мы явно видим, что значение переменной a не выйдет за допустимый диапазон значений для типа byte. Чтобы Visual Studio перестала выдавать нам ошибку преобразования, перепишем этот пример следующим образом:

byte a = 10; 
a = (byte)(a + 100);

здесь мы во второй строке использовали выражение приведения. То есть, чтобы произвести явное приведение мы в круглых скобках указываем тип данных к которому необходимо привести какое-либо значение или переменную. В нашем случае мы производим явное преобразование всего выражения a+100, поэтому мы все выражение также заключили в круглые скобки.

Теперь изменим наш пример следующим образом:

byte a = 10; 
a = (byte)(a + 300);
Console.WriteLine(a);

Какой результат мы увидим в консоли? А увидим мы значение 54. Дело в том, что тип intимеет разрядность 32 бита, а тип byte — всего 8 бит, поэтому при преобразовании компилятор отбросит старшие биты числа, представленного в двоичной системе счисления и, в результате число: 00000100110110 (310 в десятичной системе) превратится в 00110110 (54 в десятичной системе).

Этот пример, несмотря на свою простоту, достаточно наглядно демонстрирует нам, что может произойти, если неверно выбрать тип данных и произвести явное преобразование, не считаясь с допустимыми диапазонами типов данных и их разрядностью.

Итого

При работе с типами данных в C# мы можем преобразовывать данные из одного типа в другой. При этом, платформа .NET может сама произвести необходимое преобразование базового типа, если такое преобразование является расширяющим, например, из byte в int. Также, мы можем использовать выражения преобразования для того, чтобы самостоятельно (явно) преобразовать один тип данных в другой. При явном преобразовании мы (разработчики) берем на себя все риски, связанные с потерей данных и возможными ошибками преобразования.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии