$ sudo teach IT
Модуль 5 · Коллекции

Урок 5.5 — Все типы данных

Сводка типов C#: значимые и ссылочные, стек и куча, nullable и var.

Типы данных — это основа любой программы. Понимание, как C# управляет памятью, чем отличается struct от class, и что такое «значимые» и «ссылочные» типы, отличает начинающего программиста от уверенного. В этом уроке мы соберём все знания о типах в одну картину.

🏗️

Значимые (value) vs ссылочные (reference) типы

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

Значимые типы (Value Types)

Значимые типы хранят значение напрямую. Когда ты присваиваешь одну переменную другой — создаётся копия значения. Они хранятся на стеке (stack) — очень быстрой, но ограниченной по размеру памяти:

C# · Value type — копирование
int a = 10;
int b = a;     // b получает КОПИЮ значения a
b = 20;        // меняется только b
Console.WriteLine(a); // 10 — a не изменилось!

Ссылочные типы (Reference Types)

Ссылочные типы хранят ссылку на данные. Сами данные лежат в куче (heap) — более медленной, но практически неограниченной памяти. Когда ты присваиваешь одну переменную другой — копируется ссылка, а данные остаются общими:

C# · Reference type — копирование ссылки
int[] arr1 = { 1, 2, 3 };
int[] arr2 = arr1;   // arr2 получает ССЫЛКУ на тот же массив
arr2[0] = 999;       // меняем через arr2
Console.WriteLine(arr1[0]); // 999 — arr1 тоже изменился!

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

Стек (Stack) vs Куча (Heap)

Стек (Stack)
Куча (Heap)
Очень быстрый
Медленнее (но всё ещё быстро)
Маленький (≈1 МБ под поток)
Большой (ограничен RAM)
Автоматическое управление (LIFO)
Сборка мусора (GC)
Хранит: локальные переменные, параметры
Хранит: объекты, строки, массивы
Очищается при выходе из метода
Очищается GC, когда нет ссылок
📋

Полная таблица встроенных типов C#

Вот все встроенные (built-in) типы C# и их .NET-эквиваленты:

C# тип
.NET тип
Размер
Диапазон
byte
Byte
1 байт
0 … 255
sbyte
SByte
1 байт
−128 … 127
short
Int16
2 байта
−32 768 … 32 767
ushort
UInt16
2 байта
0 … 65 535
int
Int32
4 байта
−2.1 млрд … 2.1 млрд
uint
UInt32
4 байта
0 … 4.3 млрд
long
Int64
8 байт
±9.2×10¹⁸
ulong
UInt64
8 байт
0 … 1.8×10¹⁹
float
Single
4 байта
±1.5×10⁻⁴⁵ … ±3.4×10³⁸
double
Double
8 байт
±5.0×10⁻³²⁴ … ±1.7×10³⁰⁸
decimal
Decimal
16 байт
28-29 знаков, для денег
bool
Boolean
1 байт
true / false
char
Char
2 байта
Один символ Unicode
string
String
переменный
Строка текста (ссылочный!)
🧱

Struct vs Class

В C# ты можешь создавать свои типы. struct — это значимый тип (value type), class — ссылочный (reference type). Выбор между ними — важное архитектурное решение:

struct
class
Значимый тип (value type)
Ссылочный тип (reference type)
На стеке (или inline в объектах)
В куче (heap)
Копируется при присваивании
Копируется ссылка
Не может быть null
Может быть null
Нет наследования
Есть наследование
Для маленьких, неизменяемых
Для больших/изменяемых объектов
C# · Struct vs Class
struct Point { public int X; public int Y; }
class Person { public string Name; public int Age; }

Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1;
p2.X = 100;
Console.WriteLine(p1.X); // 10

Person person1 = new Person { Name = "Анна", Age = 25 };
Person person2 = person1;
person2.Name = "Борис";
Console.WriteLine(person1.Name); // "Борис"
❓

Nullable типы: int?, double?

Значимые типы (int, double, bool, struct) не могут быть null. Но иногда нужно выразить «значения нет». Для этого существуют nullable-типы — с вопросительным знаком:

C# · Nullable типы
int? age = null;
double? price = null;
bool? isActive = null;

if (age.HasValue)
    Console.WriteLine($"Возраст: {age.Value}");
else
    Console.WriteLine("Возраст неизвестен");

// Оператор ?. — безопасный доступ
string? name = null;
int? length = name?.Length;  // null (не упадёт!)

// Оператор ?? — значение по умолчанию
int actualAge = age ?? 0;
string displayName = name ?? "Гость";
🔄

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

C# — язык со строгой типизацией. Есть два вида преобразований.

Неявное (implicit)

Безопасное, без потерь:

C# · Неявное
int a = 100;
double b = a;  // int → double
long c = a;    // int → long

Явное (explicit)

С потерей данных — оператор приведения (тип):

C# · Явное
double pi = 3.14159;
int intPi = (int)pi;  // 3

Парсинг строк

C# · Парсинг
int num = int.Parse("42");
if (int.TryParse("42", out int result)) { }
double d = double.Parse("3.14");
string text = 42.ToString();
string price = 1234.5.ToString("C");
🔤

Ключевое слово var

var — сокращение для «пусть компилятор сам определит тип». Переменная полностью типизирована, просто тип выводится:

C# · var
var age = 25;           // int
var name = "Анна";      // string
var price = 99.9;       // double
var list = new List<int>(); // List<int>

// var x;  // ❌ Ошибка! Нужна инициализация
var x = 10;
// x = "hello";  // ❌ x — это int!
📊

Сводная таблица: value vs reference

Value types
Reference types
int, double, bool, char
string
struct, enum
class, array, delegate
decimal, long, float
List, Dictionary, record
На стеке
В куче (ссылка на стеке)
🧩

Проверь себя — вопросы

Вопрос 1

Что выведет: int a = 5; int b = a; b = 10; Console.WriteLine(a);?

Ответ: 5 (int — value type, копируется)

Вопрос 2

Может ли int быть null?

Ответ: Обычно нет. int? — может.

Вопрос 3

Что выведет: double d = 3.14; int i = (int)d; Console.WriteLine(i);?

Ответ: 3 (потеря дробной части при явном приведении)

Вопрос 4

string — это value или reference type?

Ответ: Reference type (ссылочный, в куче). Хотя используется как value во многих сценариях.

📌

Что важно запомнить

1️⃣
Value types хранят значение напрямую. Копируются при присваивании. На стеке. Примеры: int, double, bool, char, struct, enum.
2️⃣
Reference types хранят ссылку на данные. Копируется ссылка. Данные в куче. Примеры: string, class, array, delegate, List, Dictionary.
3️⃣
Nullable — int? может быть null. ?? — значение по умолчанию. ?. — безопасный доступ.
4️⃣
Неявное — без потерь (int → double). Явное — с потерей (double → int через (int)).
5️⃣
var — компилятор выводит тип. Тип фиксирован. Обязательна инициализация.

Тест: 5.5: Все типы данных

3 вопроса

Типы значений и ссылок

Premium