В чем разница между классом и структурой в C#?

«В чем разница между классом и структурой в C#?» — вопрос из категории C# Core, который задают на 51% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основные различия между class (ссылочный тип) и struct (значимый тип) в C#:

1. Расположение в памяти и поведение при копировании:

  • Класс: Экземпляры размещаются в управляемой куче. При присваивании переменной копируется только ссылка на объект.
  • Структура: Экземпляры обычно размещаются в стеке (или внутри родительского объекта). При присваивании копируется всё значение (полное клонирование данных).

2. Наследование:

  • Класс: Поддерживает наследование (кроме sealed классов).
  • Структура: Не может быть базовой для других типов и не поддерживает наследование (но реализует интерфейсы). Все структуры неявно sealed.

3. Значение по умолчанию и null:

  • Класс: Значение по умолчанию — null.
  • Структура: Не может быть null (если не используется Nullable<T>). При создании без конструктора все поля инициализируются своими значениями по умолчанию.

4. Конструкторы:

  • Структура: Всегда имеет неявный конструктор без параметров, который обнуляет все поля. Вы не можете определить собственный конструктор без параметров в версиях до C# 10.

Когда что использовать:

  • Используйте struct для:

    • Небольших, неизменяемых (или преимущественно неизменяемых) данных (менее 16 байт).
    • Логических группировок простых типов (например, точка Point, цвет RGB).
    • Частого создания и удаления в критичных к производительности сценариях (меньше нагрузка на сборщик мусора).
  • Используйте class для:

    • Объектов с поведением (методами) и сложным состоянием.
    • Данных, которые часто передаются по ссылке.
    • Когда требуется наследование или полиморфизм.

Пример:

// Структура - значимый тип
public struct Point
{
    public int X;
    public int Y;
    // Копируется по значению
}

// Класс - ссылочный тип
public class Person
{
    public string Name;
    // Копируется по ссылке
}

// Использование
Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1; // Создается ПОЛНАЯ копия данных
p2.X = 100; // p1.X останется 10

Person per1 = new Person { Name = "Alice" };
Person per2 = per1; // Копируется только ссылка
per2.Name = "Bob"; // per1.Name тоже станет "Bob"