Почему в структуре нет конструктора по умолчанию?csharp-135

Основная причина: семантика типов значений

Ключевое отличие структур (value types) от классов (reference types) в C# лежит в их поведении при создании и копировании:

  1. Гарантия инициализации: CLR гарантирует, что все поля структур будут нулевыми (default) при создании
  2. Требование к производительности: Структуры часто используются в массовых операциях, где накладные расходы критичны
// Такой конструктор запрещен в структурах
public struct Point
{
    public int X;
    public int Y;

    // Ошибка компиляции: нельзя определять конструктор без параметров
    public Point()
    {
        X = 0;
        Y = 0;
    }
}

Технические ограничения CLR

  1. Особенности выделения памяти:

    • Массивы структур создаются одним блоком памяти
    • Поля структур инициализируются нулями "оптом"
    • Вызов конструктора для каждого элемента массива убил бы производительность
  2. default(T) семантика:

    • Выражение default(Point) должно работать без вызова конструктора
    • Это фундаментальное требование для generics

Исторические причины

  1. Обратная совместимость с ранними версиями .NET
  2. Сходство с С/C++ где POD (Plain Old Data) типы ведут себя аналогично

Обходные пути

  1. Инициализация через параметризованный конструктор:
public struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}
  1. Использование readonly struct (C# 7.2+):
public readonly struct ImmutablePoint
{
    public int X { get; }
    public int Y { get; }

    public ImmutablePoint(int x = 0, int y = 0)
    {
        X = x;
        Y = y;
    }
}
  1. Фабричные методы:
public struct Point
{
    public int X;
    public int Y;

    public static Point CreateDefault() => new Point { X = 0, Y = 0 };
}

Изменения в C# 10 и .NET 6+

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

  1. Конструктор должен быть публичным
  2. Все поля должны быть явно инициализированы
  3. Не работает с default(T) и массивами
// Только в C# 10+ с определенными условиями
public struct Point
{
    public int X;
    public int Y;

    public Point()
    {
        X = 0;
        Y = 0;
    }
}

Почему это все еще проблематично

  1. Неожиданное поведение:
Point[] points = new Point[100]; // Все равно будет zero-initialized
  1. Ограниченная поддержка в generics:
T Create<T>() where T : new() => new T();
// Для структур вызовет конструктор по умолчанию только если он явно определен

Резюмируем:

отсутствие конструкторов по умолчанию в структурах — это осознанное проектное решение, продиктованное требованиями производительности, семантикой типов значений и ограничениями CLR. Современные версии C# добавляют ограниченную поддержку, но основное поведение остается для сохранения обратной совместимости и эффективности.