Подтвердить что ты не робот

Должен ли мы всегда включать конструктор по умолчанию в класс?

Мне задали этот вопрос коллега, который должен всегда включать конструктор по умолчанию в класс? Если да, то почему? Если нет, почему бы и нет?

Пример

public class Foo {

    Foo() { }

    Foo(int x, int y) {
        ...
    } 

}

Мне также интересно узнать об этом от экспертов.

4b9b3361

Ответ 1

Вы должны помнить, что если вы не предоставите перегруженный конструктор, компилятор создаст для вас конструктор по умолчанию. Это означает, что если вы просто

public class Foo
{ 
} 

Компилятор будет генерировать это как:

public class Foo
{ 
    public Foo() { }  
} 

Однако, как только вы добавите другой конструктор

public class Foo
{ 
    public Foo(int x, int y)
    { 
        // ... 
    }  
} 

Компилятор больше не будет автоматически генерировать конструктор по умолчанию для вас. Если класс уже использовался в другом коде, который полагался на наличие конструктора по умолчанию, Foo f = new Foo();, этот код теперь сломался.

Если вы не хотите, чтобы кто-то мог инициализировать класс без предоставления данных, вы должны создать конструктор по умолчанию, который private должен быть явно о том, что вы запрещаете создание экземпляров без входных данных.

Однако есть моменты, когда необходимо предоставить конструктор по умолчанию (будь то открытый или закрытый). Как уже упоминалось ранее, для некоторых типов сериализации требуется конструктор по умолчанию. Существуют также случаи, когда класс имеет несколько параметризованных конструкторов, но также требует инициализации "нижнего уровня", и в этом случае может использоваться частный конструктор по умолчанию, который привязан к параметризуемым конструкторам.

public class Foo
{
   private Foo()
   {
      // do some low level initialization here
   }

   public Foo(int x, int y)
      : this()
   {
      // ...
   }

   public Foo(int x, int y, int z)
      : this()
   {
      // ...
   }
}

Ответ 2

Некоторые вещи (например, сериализация) требуют конструктора по умолчанию. Однако вне этого конструктор по умолчанию должен быть добавлен только в том случае, если это имеет смысл.

Например, если свойства Foo.X и Foo.Y неизменяемы после построения, конструктор по умолчанию на самом деле не имеет смысла. Даже если бы это было использовано для "пустого" Foo, более доступный для поиска был бы статичный аксессуар Empty.

Ответ 3

Я бы сказал нет, определенно не всегда. Предположим, у вас есть класс с некоторыми полями readonly, которые должны быть инициализированы до некоторого значения, и нет разумных значений по умолчанию (или вы не хотите, чтобы они были)? В этом случае я не думаю, что конструктор без параметров имеет смысл.

Ответ 4

Наличие конструктора по умолчанию - это только хорошая идея, если имеет смысл иметь такой объект.

Если вы создаете объект, который не находится в правильном состоянии от такого конструктора, то единственное, что он может сделать, это ввести ошибку.

Ответ 5

Да, обычно в большинстве случаев лучше писать конструктор по умолчанию.

Как правило, если вы не укажете какой-либо конструктор,.NET автоматически создаст для вас конструктор по умолчанию.

Сериализация требует конструктора по умолчанию.

Ответ 6

В качестве побочного примечания при использовании структуры вместо класса обратите внимание на то, что нет способа оставить конструктор по умолчанию, и его невозможно определить самостоятельно, поэтому независимо от того, какие конструкторы вы определите, убедитесь, что состояние структуры по умолчанию (когда все переменные установлены в их состояние по умолчанию (обычно 0 для типов значений и null для ссылочных типов) не нарушат вашу реализацию структуры.

Ответ 7

В большинстве случаев конструктор по умолчанию является хорошей идеей. Но поскольку вы используете слово "всегда", все, что нужно, это один контрпример. Если вы посмотрите на Framework, вы найдете много. Например, System.Web.HttpContext.

Ответ 8

Общий тип может быть создан только с помощью С# (без отражения), если он имеет конструктор по умолчанию. Кроме того, должно быть указано ограничение типа new() generic type:

void Construct<T>()
    where T : new()
{
    var t = new T();
    ...
}

Вызов этого метода с использованием типа как аргумента типа общего типа, который не имеет конструктора по умолчанию, приводит к ошибке компилятора.