Основы C#
C# — компилируемый язык со статической типизацией: у каждой переменной есть тип, известный компилятору, и большую часть ошибок он находит до запуска. Исходник превращается в IL внутри сборки, а машинный код появляется при выполнении — его порождает JIT-компилятор CLR. Простейшая программа сегодня — одна строка Console.WriteLine("Hello"); без класса и Main: это инструкции верхнего уровня, а using System; подставляют неявные using.
Эта тема — фундамент для всех остальных. Как объявить переменную и почему её нельзя прочитать до присваивания. Какие есть встроенные типы и чем double отличается от decimal. Почему 7 / 2 равно 3, а переполнение int по умолчанию не бросает исключения. Когда преобразование происходит само, а когда нужно явное приведение или TryParse. Почему строку нельзя изменить на месте, а == сравнивает её содержимое. Разбор по слоям — ниже.
Карта темы
- Структура программы — путь от
.csк IL и машинному коду, инструкции верхнего уровня противstatic void Main, вывод в консоль, ошибки и предупреждения компилятора. - Переменные — объявление, инициализация и присваивание, правило определённого присваивания, область видимости,
varиconst. - Встроенные типы — целые типы,
float/double/decimal,bool,char,string; литералы и суффиксы,MinValue/MaxValue, значения по умолчанию. - Операторы — целочисленное деление и
%,++/--, сокращённые&&и||, приоритет, переполнение иchecked, точностьdouble, деление на ноль. - Преобразования типов — неявное расширение, явное приведение с отбрасыванием дроби,
Parse/TryParse,Convertи влияние культуры. - Строки — индексация и
Length, управляющие последовательности, буквальные и необработанные литералы, интерполяция, неизменяемость и сравнение через==.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Ждать 3.5 от 7 / 2 | Оба операнда int — деление целочисленное, результат 3; нужен хотя бы один double: 7.0 / 2 |
Считать, что int следит за переполнением | По умолчанию арифметика не проверяется: int.MaxValue + 1 даёт -2147483648 без исключения; проверку включает checked |
Хранить деньги в double | 0.1 + 0.2 == 0.3 — False; для денег и точных десятичных дробей берут decimal |
| Читать локальную переменную до присваивания | Ошибка компиляции CS0165: в отличие от полей, локальные переменные не получают значения по умолчанию |
Ждать округления от (int)3.99 | Приведение отбрасывает дробную часть: 3, а (int)-3.99 даёт -3 |
Разбирать ввод через int.Parse | На строке "4x" — FormatException; для ввода, который может быть неверным, есть int.TryParse |
Думать, что s.ToUpper() меняет s | Строки неизменяемы: метод возвращает новую строку, и без присваивания она теряется |
Писать console.WriteLine | C# различает регистр: ошибка CS0103, имени console не существует |
Значение для собеседований
Основы редко спрашивают отдельным блоком, но именно на них построены задачи «что выведет этот код». Интервьюер проверяет не синтаксис, а модель: понимаете ли вы, что тип результата задают операнды, что int молча переполняется, что double — двоичная дробь, а строка неизменяема.
Что обычно проверяют:
- Результат
7 / 2,-7 / 2,-7 % 3и почему он такой. - Поведение
int.MaxValue + 1и разницуcheckedиunchecked. - Когда брать
decimal, а когдаdouble, и почему0.1 + 0.2 != 0.3. - Разницу
(int)x,Convert.ToInt32(x)иint.Parse(s), и зачем нуженTryParse. - Что такое
varи почему это не динамическая типизация. - Почему строка неизменяема и что сравнивает
==для строк.
Типичный неверный ответ: «double подойдёт для денег, просто округлим при выводе». Это открывает разговор о том, что double хранит двоичную дробь и 0.1 в нём неточна, ошибки копятся при сложении, а decimal хранит число в десятичной системе и считает копейки точно.