Private .ctor абстрактного класса

183
20 октября 2017, 11:48

Добрый день!

Тут на днях поймал интересный кейс:

public abstract class BaseClass
{
     private BaseClass(int i)
    {
        Console.WriteLine("Constructor of BaseClass, accept i:" + i);
    }
}
    public class DerivedClass : BaseClass
    {
// В этом месте, естественно, возникает ошибка компиляции, т.к. нет доступа к private конструктору базового класса и компилятор не пропускает код в компиляцию
    public DerivedClass(int i, int z) : base(2)
    {
        Console.WriteLine("Constructor of DerivedClass, accept i:{0}, z:{1}", i, z);
    }
}

Скомпилировано в VS2017, .Net 4.6.1

Собственно вот в чём вопрос: Почему компилятор C# позволяет объявить единственный private конструктор базового класса, если это приведёт к невозможности его наследования?

Если убрать DerivedClass и оставить только базовый, то компилятор не видит проблем и свободно компилирует код, с полностью непригодным классом. Подобный код запросто компилируется:

    public abstract class BaseClass
{
    private BaseClass(int i)
    {
        Console.WriteLine("Constructor of BaseClass, accept i:" + i);
    }
}

Или же это можно как то использовать?

Answer 1

Приватный конструктор у абстрактного класса может использоваться:

  1. чтобы ограничить множество наследников класса вложенными классами (например, для создания закрытой иерархии классов):

    public abstract class BaseClass
    {
        private BaseClass(int i)
        {
            Console.WriteLine("Constructor of BaseClass, accept i:" + i);
        }
        public class DerivedClass : BaseClass
        {
            public DerivedClass() : base(2) { } // разрешено
        }
    }
    
    public class DerivedClass : BaseClass
    {
        public DerivedClass() : base(2) { } // ошибка
    }
  2. вместо модификатора static при объявлении классов являющихся наборами статических методов (актуально для старых версий языка, где не было статических классов):

    public abstract class Utils
    {
        private Utils() {}
        public static void Foo()
        {
            Console.WriteLine("Hello, world!");
        }
    }
  3. для объявления невозможного типа, переменные которого могут иметь только значение null, а в not nullable варианте не могут существовать:

    public abstract class Void 
    {
        private Void() { }
    }

Впрочем, в двух последних случаях модификатор abstract - вкусовщина и может не использоваться.

Ну и последнее. У компилятора нет задачи проверки осмысленности вашей программы - а значит не у всех комбинаций языковых конструкций есть хоть какой-то смысл. Особенно богата на потенциально бессмысленные конструкции последняя версия языка, где по-убирали многие старые ограничения с мотивацией "а почему бы и нет?" :-)

READ ALSO
Создание модели ADO NET из файла базы данных SDB

Создание модели ADO NET из файла базы данных SDB

Есть файл БД с расширением SDBКак его подключить в Visual Studio и создать из не модель, для последующей полноценной работы через Linq

242
Устранение замыленности формы

Устранение замыленности формы

Этот вопрос исходит из этого вопросаМне не нравится что настройки, которые устраняют "замыленность" формы содержаться в app

219
Не удается загрузить файл или сборку

Не удается загрузить файл или сборку

Написал библиотеку классов на с#(ну как написал, скопировал по гайдику)Подключил через "Add/Reference" к другому проекту, в котором требовалась данная...

354