Перейти к содержимому
Теория · Переменные и типы · урок 7 из 8

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

Вернёмся к коробкам разной формы. Скопировать значение из маленькой коробки в большую можно без вопросов: всё поместится. Из большой в маленькую — только с вашего согласия, ведь часть значения может не влезть и потеряться.

Бывает и задача посложнее. Значение "42" — это текст, а не число, и строку int n = "42"; компилятор не примет. А данные от пользователя или из файла приходят именно текстом. Чтобы с ними считать, текст нужно превратить в число. Разберём все три случая.

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

Из int в long и в double значение переходит само:

C#
int apples = 12;
long many = apples;
double exact = apples;
Console.WriteLine(many); // 12
Console.WriteLine(exact); // 12

Давайте разберём по строкам:

  1. long many = apples; кладёт int в коробку long: любое значение int поместится в неё с запасом.
  2. double exact = apples; превращает целое 12 в дробное 12.0.
  3. Обе строки печати выводят 12: double с нулевой дробной частью печатается без .0.

Такое преобразование называют неявным: C# выполняет его без вашей команды, ведь любое значение int помещается в long и double целиком. В обратную сторону он сам не переводит. long в int и double в int — ошибка компиляции CS0266: значение может не поместиться.

Явное приведение

Когда вы согласны потерять часть значения, напишите нужный тип в скобках перед значением: (int)price. Это явное приведение:

C#
double price = 3.99;
int whole = (int)price;
Console.WriteLine(whole); // 3
Console.WriteLine((int)-3.99); // -3

Разберём, что получилось:

  1. (int)price отбрасывает дробную часть: из 3.99 выходит 3, а не 4.
  2. (int)-3.99 даёт -3: отбрасывание дроби сдвигает число к нулю, а не вниз.

Здесь аналогия с коробками неточна. Приведение не утрамбовывает значение и не ищет ближайшее целое. Оно отрезает всё, что стоит после точки.

Parse, Convert и ToString

У C# есть и готовые средства перевода — из строки в число, из дробного числа в целое с округлением и из любого значения в строку:

C#
int year = int.Parse("2026");
Console.WriteLine(year); // 2026
Console.WriteLine(Convert.ToInt32(2.5)); // 2
Console.WriteLine(Convert.ToInt32(3.5)); // 4
string text = year.ToString();
Console.WriteLine(text + text); // 20262026

int.Parse

int.Parse("2026") читает строку из цифр и возвращает число 2026. Если в строке не целое число, например "4.5", программа остановится с ошибкой — пример в конце урока.

Convert.ToInt32

Convert.ToInt32 переводит в int значения разных типов, в том числе double. В отличие от приведения, он округляет: к ближайшему целому, а ровно посередине — к чётному. Поэтому 2.5 даёт 2, а 3.5 — 4. Такое округление называют банковским.

На собеседовании часто спрашивают, чем (int)x отличается от Convert.ToInt32(x). Ответ: приведение отбрасывает дробную часть, а Convert.ToInt32 округляет до ближайшего целого.

ToString

Обратный путь — ToString(): он превращает значение в строку. year.ToString() даёт текст "2026", поэтому text + text склеивает две строки, а не складывает числа — выходит 20262026.

Частая ошибка

В int.Parse передали строку, в которой, кроме числа, есть слово:

C#
int count = int.Parse("12 apples"); // ✗
Console.WriteLine(count);
TEXT
Unhandled exception. System.FormatException: The input string '12 apples' was not in a correct format.

Эта программа компилируется: компилятор не проверяет, что лежит внутри строки. Ошибка случается при запуске. Программа останавливается на строке с int.Parse и печатает отчёт об ошибке. Его первая строка показана выше. До Console.WriteLine дело не доходит.

int.Parse принимает только строку с целым числом: знак в начале и пробелы по краям допустимы, а буквы и точка — нет.

Главное

  • Из int в long и double значение переходит неявно, а в обратную сторону нужно явное приведение.
  • (int)3.99 даёт 3, а (int)-3.99 — -3: приведение отбрасывает дробную часть.
  • Convert.ToInt32 округляет к ближайшему целому, а ровно посередине — к чётному: 2.5 даёт 2.
  • int.Parse превращает строку в число и останавливает программу, если в строке не целое число; ToString() делает обратное.