Может ли структура (struct) в C# наследоваться от другой структуры?

«Может ли структура (struct) в C# наследоваться от другой структуры?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, структура в C# не может наследоваться от другой структуры или класса. Все структуры неявно являются запечатанными (sealed) и наследуются только от типа System.ValueType (который, в свою очередь, наследуется от System.Object). Это фундаментальное отличие от классов, поддерживающих наследование.

Пример, который вызовет ошибку компиляции:

public struct Point2D
{
    public int X;
    public int Y;
}

// ОШИБКА CS0527: 'Point3D': type in interface list is not an interface
public struct Point3D : Point2D // Наследование структур запрещено
{
    public int Z;
}

Почему это ограничение существует?

  1. Семантика значений: Структуры — типы значений, хранящиеся в стеке или внутри других объектов. Наследование потребовало бы механизма виртуальных таблиц (vtable) и динамической диспетчеризации, что противоречит их простой и эффективной модели памяти.
  2. Размер и компоновка: Размер структуры должен быть известен и фиксирован во время компиляции. Наследование могло бы приводить к изменению размера, что нарушило бы работу стековых операций и sizeof.
  3. Производительность: Отсутствие наследования позволяет избежать накладных расходов, связанных с проверками типов и приведением, что критично для высокопроизводительных сценариев, для которых и предназначены структуры.

Альтернативы для повторного использования кода в структурах:

  • Композиция (предпочтительно): Включите экземпляр базовой структуры как поле.

    public struct Point3D
    {
        public Point2D Point2D; // Композиция
        public int Z;
    
        public int X { get => Point2D.X; set => Point2D.X = value; }
        public int Y { get => Point2D.Y; set => Point2D.Y = value; }
    }
  • Интерфейсы: Структуры могут реализовывать интерфейсы. Это позволяет полиморфизм через интерфейсную ссылку (но с боксингом).
    public interface IPoint { int X { get; } int Y { get; } }
    public struct Point2D : IPoint { ... }
  • Методы расширения: Добавьте общую функциональность через статические методы расширения.

Вывод: Используйте структуры для небольших, неделимых данных, где важна производительность и семантика значений. Для иерархий типов и полиморфизма используйте классы.