Классификация типов значений и ссылочных типов
Предопределенные встроенные типы
| Категория | Включаемые типы |
|---|---|
| Типы значений (базовые числовые / логические / символьные) | Целые со знаком: sbyte, short, int, longЦелые без знака: byte, ushort, uint, ulongВещественные / высокоточные: float, double, decimalЛогический: boolСимвольный: char |
| Ссылочные типы (встроенные ссылки) | object (базовый класс всех типов), string, dynamic |
Пользовательские типы
| Категория | Типы |
|---|---|
| Типы значений | struct (структура), enum (перечисление) |
| Ссылочные типы | class, interface, delegate, array (массив) |
Как мы обсуждали на прошлом занятии, данные ссылочных типов всегда хранятся в куче. Данные типов значений могут располагаться как в куче, так и в стеке.
Сама ссылка ссылочного типа может быть размещена как в куче, так и в стеке.
Место хранения переменной типа значения или ссылки ссылочного типа зависит от того, является ли она членом типа или локальной переменной внутри функции.
Четыре категории переменных
| Тип переменной | Определение и назначение |
|---|---|
| Локальная переменная Local variable | Временные данные внутри метода, не является членом типа; Хранится в стеке Не инициализируется автоматически |
| Поле Field | Данные, привязанные к классу / структуре, относится к членам типа; Поля классов хранятся в куче Поля структур следуют расположению самой структуры; Инициализируется автоматически |
| Параметр Parameter | Временная переменная для передачи аргументов в метод, не является членом типа; Хранится в стеке Не инициализируется автоматически |
| Элемент массива Array element | Отдельная запись внутри массива; Все хранятся в куче Инициализируется автоматически |
Автоматическая инициализация означает, что компилятор присваивает переменной значение по умолчанию, даже если программист не указал начальное значение.
Более простое резюме
| Тип переменной | Место хранения | Автоматическая инициализация |
|---|---|---|
| Локальная переменная | Стек / Стек + Куча | Нет |
| Поле класса | Куча | Да |
| Поле структуры | Стек / Куча | Да |
| Параметр метода | Стек | Нет |
| Элемент массива | Куча | Да |

Объявление переменных
Формат:Тип ИмяПеременной;
int var2;Code language: C# (cs)
Эта строка объявляет переменную и выполняет две основные задачи:
- Сообщает компилятору, что var2 — переменная типа int с именем var2.
- Компилятор выделяет область памяти. Расположение памяти (в куче или стеке) зависит от контекста: является ли переменная локальной, параметром, полем и т.д.

Инициализатор переменных (Initializer)
Синтаксис:Тип ИмяПеременной = НачальноеЗначение;
Пример:int var2 = 17;
Инициализатор — это механизм компилятора для подготовки переменных. Некоторые переменные программист должен инициализировать явно в коде, другие можно оставить на усмотрение автоматического инициализатора.
Неинициализированная локальная переменная имеет неопределенное значение, вызовет ошибку компиляции и не может использоваться напрямую;
Поля, элементы массивов и другие переменные с автоматической инициализацией получают значения по умолчанию: числовые типы — 0, ссылочные типы — null.
Рассмотрим пример:
class Program
{
static void Main(string[] args)
{
int times = 100;
Person person = new Person();
}
}
class Person
{
public int age;
}
Code language: C# (cs)
В простом примере внутри функции Main объявлена переменная типа значения times и ссылочная переменная person. В ссылочном типе присутствует поле age.
Для age не задано начальное значение, а переменной times мы присвоили значение вручную.
Данный код компилируется без ошибок.

Если убрать начальное значение 100 у times и переписать код так:

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

Окно списка ошибок покажет детальную информацию

Важно: ошибка появится только если переменная times используется в коде. Если переменная нигде не вызывается, ошибки не будет, компиляция пройдёт успешно.
class Program
{
static void Main(string[] args)
{
int times;
Person person = new Person();
}
}
Code language: C# (cs)
В случае полей типа, например поля age в классе Person ниже, компиляция и запуск возможны даже без явной инициализации.
class Program
{
static void Main(string[] args)
{
int times = 100;
Console.WriteLine(times);
Person person = new Person();
Console.WriteLine(person.age);
}
}
class Person
{
public int age;
}
Code language: C# (cs)

На экране мы увидим вывод 0. Поскольку age является полем класса и не инициализировано вручную, инициализатор присвоит ему значение по умолчанию. Для int это ноль, у разных типов значения по умолчанию отличаются.
Объявление нескольких переменных в одной строке
- В одной строке можно объявлять только переменные одного типа;
- Имена переменных разделяются запятой, допускается смешивать инициализированные и неинициализированные переменные;
- Запрещено смешивать разные типы данных в одной строке.
// Корректно
int var3 = 7, var4, var5 = 3;
double var6, var7 = 6.52;
// Ошибка! Смешение int и float
int var8, float var9;
Code language: JavaScript (javascript)
Чтение значения переменной
Чтобы получить значение из памяти, достаточно написать имя переменной:
Console.WriteLine("{0}", var2);Code language: JavaScript (javascript)

Переменная