Преобразование базовых типов данных в C# - C# и .NET

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

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

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

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

int i = 0; //инициализировали целочисленную переменную
i = "s"; //нельзя присвоить целочисленной переменной строку

В Visual Studio мы получим ошибку:

Не удается неявно преобразовать тип “string” в “int”.

Что значит “неявно”? А можно ли тогда преобразовать строку в число явно? Эти и другие вопросы вполне возможно возникают у каждого новичка в C#. Поэтому мы сегодня и будем детально разбираться с механизмами преобразования базовых типов данных в C#, чтобы в дальнейшем мы могли решать более сложные задачи, чем задачи вывода “Hello, World!” и перебора символов строки в консоли.

Виды преобразований типов данных в C#

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

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

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

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

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

здесь переменные a и b имеют разные типы данных. И без неявного преобразования мы должны были бы получить ошибку, как показано выше. Но такой код вполне успешно скомпилируется и запустится. Вспомним информацию по типам данных в C#:

Псевдоним типа в C# Описание Размер, байт
byte целое число в диапазоне от 0 до 255 1
int целое число в диапазоне от -2 147 483 648 до 2 147 483 647 4

Обратите внимание на размеры типов данных: int– это больший целочисленный тип, чем byteпоэтому срабатывает неявное преобразование и значение переменной aпреобразуется в intи присваивается переменной. И, как видите, здесь нет противоречий с ранее изученным материалом – переменной присваивается значение того же типа, что и сама переменная. В C# такое преобразование также называется расширяющим — мы расширяем размер объекта (переменной) в памяти.

Для каких числовых типов данных используется неявное преобразование в C#?

Ниже представлена таблица, в которой представлены числовые типы данных для которых может применяться неявное преобразование в C#

Тип В какие типы данных может неявно преобразовываться
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.

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

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

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

Рассмотрим следующий пример:

byte a = 10;
a = a + 100;

По умолчанию, результат сложения двух целых чисел в C# имеет тип int, а переменная aимеет тип byte, который меньше по размеру, чем int. Таким образом, чтобы присвоить переменной новое значение, необходимо произвести преобразование типа результата вычисления в byte, но так как неявное преобразование производится из типов с большим размером в типы с меньшим размером, то мы получим снова ошибку:

Не удается неявно преобразовать тип “int” в “byte”.

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

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

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

Выше было сказано про потерю точности и потерю данных. Когда при явном преобразовании мы можем потерять данные? Самый очевидный пример – когда значение переменной выйдет за допустимый диапазон значения типа данных. Перепишем наш пример следующим образом:

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

Вопреки нашим ожиданиям увидеть ответ 410, в консоли мы увидим:

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

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

Старшинство битов считается слева на право: самый старший бит находится слева, самый младший – справа, если записать биты в строку

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

Преобразование данных с помощью класса Convert

С явным и неявным преобразованием числовых данных разобрались. Но как нам быть в случае, если потребуется перевести, скажем, строку в число (string -> int)? При попытке выполнить вот такой код:

int a;
string b = "123";
a = (int)b;

Мы получим ошибку:

Не удается преобразовать тип “string” в “int”

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

ToBoolean(value)
ToByte(value)
ToChar(value)
ToDateTime(value)
ToDecimal(value)
ToDouble(value)
ToInt16(value)
ToInt32(value)
ToInt64(value)
ToSByte(value)
ToSingle(value)
ToUInt16(value)
ToUInt32(value)
ToUInt64(value)

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

Console.WriteLine("Введите целое число от 0 до 10: ");
int number = Convert.ToInt32(Console.ReadLine());
if ((number > 10) || (number < 0))
    Console.WriteLine("Введенное число выходит за заданный диапазон");
else
    Console.WriteLine($"Число {number} подходит");
Console.ReadKey();

здесь мы используем метод ToInt32(value), чтобы преобразовать введенную пользователем строку в целое число типа intи, в зависимости от полученного значения, выводим пользователю сообщение.

В дальнейшем, при изучении C#, мы будем часто использовать класс Convertдля преобразования данных.

Преобразование данных с помощью методов типов

Практически все базовые типы данных, такие как int, double, floatи ряд других типов данных, с которыми мы ещё познакомимся, позволяют воспользоваться своими методами вида Parse()и TryParse()для получения данных из строк. Например,

int i = int.Parse("1");

В результате, переменная i получит значение 1 из строки. Методы TryParse()возвращают значение trueв том случае, если преобразование прошло успешно, что позволяет использовать эти методы в условных выражениях. Например,

int i; 
if (int.TryParse("1", out i))
    Console.WriteLine("Успешное преобразование string в int");
else
    Console.WriteLine("Ошибка преобразования string в int");

здесь, в зависимости от результата выполнения метода TryParse()мы увидим в консоли одно из двух сообщений. Конкретно в нашем примере, преобразование произойдет успешно.

Подведем итог

Преобразование базовых типов данных в C# может быть явным и неявным. Неявное преобразование производится автоматически и не требует от нас никаких действий, так как в этом случае нет риска потери данных или точности вычислений. В свою очередь, явное преобразование требуется в том случае, если есть риски потери данных или точности. Для явного преобразования нам необходимо указать выражение приведения. В случае, если нам необходимо конвертировать значения, типы которых невозможно преобразовать, используя явное или неявное преобразование (например перевести число в строку), то в этом случае, мы можем воспользоваться классом Convert, который преобразуется одни базовые типы данных в другие.

Домашнее задание №14

Домашнее задание по C#: пользователь вводит с клавиатуры сумму вклада в рублях (с точностью до копейки) и процентную ставку (целое число от 5 до 25) в процентах годовых. Рассчитать срок в месяцах, через который сумма на счёте превысит 15 000 рублей. В случае ошибки ввода данных пользователем программа должна сообщать об этом до тех пор пока ошибка не будет ликвидирована. Ошибками ввода вместо чисел других символов, например, букв русского алфавита, можно пренебречь – вводится должны только цифры и знак “запятая” для разделения целой и дробной части числа