В чем разница между типами значений (Value Type) и ссылочными типами (Reference Type) в C#?

Ответ

Различие между типами значений и ссылочными типами — фундаментальное в C#. Оно определяет, как данные хранятся в памяти, как передаются и как с ними работает сборщик мусора.

Критерий Тип значения (Value Type) Ссылочный тип (Reference Type)
Хранение Хранятся в стеке (stack) или внутри других объектов (например, полей класса). Экземпляр хранится в управляемой куче (heap), а переменная содержит ссылку (адрес) на этот объект.
Присваивание Копируется значение (создается полная независимая копия данных). Копируется ссылка (обе переменные начинают указывать на один и тот же объект в куче).
Поведение по умолчанию Не может быть null (кроме Nullable<T>). По умолчанию null (ссылка никуда не указывает).
Примеры Все примитивные типы (int, bool, double), struct, enum, tuple. class, interface, delegate, string, array, record class.

Наглядный пример:

// ТИП ЗНАЧЕНИЯ (struct)
public struct Point { public int X; public int Y; }

Point p1 = new Point { X = 5, Y = 10 };
Point p2 = p1; // КОПИРОВАНИЕ ЗНАЧЕНИЯ. p2 — новая, независимая копия.
p2.X = 100;
Console.WriteLine(p1.X); // Вывод: 5 (p1 не изменился)

// ССЫЛОЧНЫЙ ТИП (class)
public class Customer { public string Name; }

Customer c1 = new Customer { Name = "Alice" };
Customer c2 = c1; // КОПИРОВАНИЕ ССЫЛКИ. c2 и c1 указывают на один объект.
c2.Name = "Bob";
Console.WriteLine(c1.Name); // Вывод: Bob (объект изменился через c2)

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

Ответ 18+ 🔞

Давай разберём эту тему, а то многие её в упор не видят, хотя она фундаментальная, как бетонный пол в подъезде. Всё крутится вокруг того, где и как твои данные живут в памяти. Это разница между "вот он, прямо тут" и "а вот там, вон по тому адресу".

Смотри, есть два лагеря.

Типы значений (Value Types) – это как наличка в кармане. Прямо у тебя. int, double, bool, твои собственные struct'ы, enum'ы. Когда ты их присваиваешь или передаёшь в метод – ты копируешь всю пачку купюр. Новую пачку. И если в новой пачке одну бумажку поменяешь, в старой нихуя не изменится. Живут они обычно в стеке – быстро, локально, после выхода из метода их как не было.

Ссылочные типы (Reference Types) – это как ячейка в банковской ячейке. У тебя на руках не золотые слитки, а бумажка с номером ячейки (ссылка). class, string, массивы, всякие делегаты. Когда ты присваиваешь или передаёшь – ты копируешь только эту бумажку с номером. Обе бумажки теперь ведут к одной и той же ячейке. Если кто-то через свою бумажку достал слиток и на нём хуйню нацарапал – следующий, кто откроет, увидит эту же хуйню. Сами объекты-слитки живут в куче (heap), за ними следит сборщик мусора.

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

// Тип значения (struct) - как наличка
public struct Point { public int X; public int Y; }

Point p1 = new Point { X = 5, Y = 10 };
Point p2 = p1; // Пиздуй в банкомат, снимай копию. p2 - твоя личная, новая пачка.
p2.X = 100; // В своей новой пачке одну купюру порвал.
Console.WriteLine(p1.X); // Вывод: 5. А в старой пачке всё на месте, нихуя не случилось.

// Ссылочный тип (class) - как ячейка в банке
public class Customer { public string Name; }

Customer c1 = new Customer { Name = "Alice" };
Customer c2 = c1; // Не новый клиент, а ксерокс бумажки с номером ячейки! Обе бумажки ведут к одному сейфу.
c2.Name = "Bob"; // Пришли, открыли ячейку по бумажке c2 и заменили табличку с именем внутри.
Console.WriteLine(c1.Name); // Вывод: Bob. Пришли по бумажке c1 – а там уже Боб! Потому что ячейка-то одна, блядь!

Главный вывод, который в лоб надо зарубить: Ссылочные типы – это общее хозяйство. Поменял что-то через одну переменную – затронул всех, у кого ссылка на этот объект. Типы значений – это личное, каждому своё. Скопировал – и живи спокойно, твои изменения никого, кроме тебя, не ебут.

А null? Тип значения в чистом виде null'ом быть не может, это ж конкретное значение, прямо тут. Разве что обернёшь в Nullable<int> (это int?). А ссылка – запросто может быть null, то есть бумажка есть, а номера ячейки на ней нет, иди на хуй.

Короче, запомни: копирование значения vs копирование ссылки. Всё остальное – производные от этой простой, но охуенно важной мысли.