Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое ссылочные типы?
Ссылочные типы — это типы данных в C#, которые хранят адрес памяти (ссылку) на объект, а не сами данные. Переменная ссылочного типа содержит указатель на область в управляемой памяти (heap), где находится реальный объект.
Отличие от значимых типов
// Значимый тип (struct, int, bool, etc.)
int a = 5;
int b = a; // копируется VALUE: b = 5
a = 10; // a меняется, b остаётся 5
Console.WriteLine($"a={a}, b={b}"); // a=10, b=5
// Ссылочный тип (class, string, array, delegate)
class Person
{
public string Name { get; set; }
}
var person1 = new Person { Name = "Alice" };
var person2 = person1; // копируется ССЫЛКА, не объект!
person1.Name = "Bob";
Console.WriteLine(person2.Name); // Bob! (один и тот же объект)
Основные ссылочные типы в C#
- class — пользовательские классы
- string — строки (неизменяемый ссылочный тип)
- array — массивы
- interface — интерфейсы
- delegate — делегаты/функции
- object — базовый тип всех объектов
- dynamic — динамически типизированный тип
Размещение в памяти
public class Book
{
public string Title { get; set; }
public int Pages { get; set; }
}
static void Main()
{
// Переменная book находится НА СТЕКЕ
// Сам объект находится НА КУЧЕ (heap)
Book book = new Book { Title = "C# Book", Pages = 500 };
// СТЕК КУЧА
// book ────────→ [Book объект]
// Title = "C# Book"
// Pages = 500
}
На стеке: только переменная (4 или 8 байт — адрес) На куче: весь объект со всеми полями
Поведение при передаче в методы
public class Counter
{
public int Value { get; set; }
}
static void ModifyReference(Counter counter)
{
counter.Value = 100; // изменяем сам объект
counter = new Counter { Value = 999 }; // создаём новый объект
}
static void Main()
{
var c = new Counter { Value = 10 };
ModifyReference(c);
Console.WriteLine(c.Value); // 100, не 999!
// Почему? Ссылка скопирована, но внутри метода создана новая переменная
}
Важно: когда ты передаёшь ссылочный тип, передаётся копия ссылки, а не сама ссылка. Поэтому переопределение ссылки внутри метода не влияет на исходную переменную.
null и ссылочные типы
Person person = null; // допустимо
if (person != null)
{
Console.WriteLine(person.Name); // NullReferenceException если проверку пропустить
}
// С nullable reference types (C# 8.0+)
Person? nullablePerson = null; // явно nullable
Сравнение ссылочных типов
var p1 = new Person { Name = "Alice" };
var p2 = new Person { Name = "Alice" };
var p3 = p1;
Console.WriteLine(p1 == p2); // false (разные объекты в памяти)
Console.WriteLine(p1 == p3); // true (одна ссылка)
Console.WriteLine(ReferenceEquals(p1, p2)); // false
Console.WriteLine(ReferenceEquals(p1, p3)); // true
Для сравнения содержимого переопредели Equals() и GetHashCode():
public class Person
{
public string Name { get; set; }
public override bool Equals(object obj)
{
return obj is Person p && p.Name == Name;
}
public override int GetHashCode() => Name.GetHashCode();
}
var p1 = new Person { Name = "Alice" };
var p2 = new Person { Name = "Alice" };
Console.WriteLine(p1 == p2); // false (по ссылке)
Console.WriteLine(p1.Equals(p2)); // true (по содержимому)
Производительность
- Ссылочные типы медленнее — требуют кучу и сборку мусора
- Значимые типы быстрее — размещаются на стеке
- Используй
structдля малых, часто копируемых данных - Используй
classдля больших объектов с поведением