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

Каков предпочтительный способ построения объектов в С#? Параметры или свойства конструктора?

Мне было интересно, какой предпочтительный способ создать новый объект в С#?

Возьмите класс Person:

public class Person 
{
    private string name;
    private int age;

    //Omitted..
}

Должен ли я создать его для использования:

New Person("name", 24);

или

New Person() { Name = "name", Age = 24 };

Это просто вопрос вкуса или есть веская причина использовать один над другим?

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

Я в этом прав?

4b9b3361

Ответ 1

Предпочтительный способ зависит от вашего дизайна.

Свойства конструктора предназначены для объектов, которые требуется вашему объекту для правильной сборки. То есть любые свойства, которые должен иметь объект для инициализации, должны быть в конструкторе (обычно вы не хотите, чтобы объект с частичным intialized после вызова конструктора, если вы не создаете шаблон factory или построитель и конструктор скрыт от всех, кроме factory/builder).

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

Например, у вас может быть объект, который представляет человека. Человеку требуется имя и возраст для инициализации, но адрес, на котором они живут, является дополнительной конфигурацией. Таким образом, имя и возраст - это параметры конструктора, а адрес - свойство чтения/записи.

Person johnDoe = new Person("John Doe", 24) { Address = "42 Adams Street" };

Ответ 2

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

Однако для неизменяемых типов подход конструктора является единственным разумным вариантом. Интересно (возможно), что именованные/необязательные параметры в С# 4.0 допускают нечто похожее на инициализаторы объектов для неизменяемых типов - см. Здесь.

Конструктор-подход также очень популярен для инфраструктур Inversion of Control, так как он четко рекламирует, что нужно для этого класса.

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

Несколько мыслей:

  • Вам нужны общедоступные свойства для использования Инициализаторов объектов. Поэтому, если вам что-то не нужно раскрывать, вы должны инициализировать их с помощью параметра конструктора.

  • Если вы проверите IL, вы обнаружите, что Object Initializer не является "атомарным". Если вы пишете такой код (не то, что я рекомендую, просто пример):

    using (p = New Person() {Name = GetName(), Age = GetAge()})
    {
      //blah, blah
    }
    

    Если в GetAge() есть исключение, вы создадите экземпляр Person в поврежденном состоянии. Хуже того, вы никогда не сможете войти в область использования, и этот экземпляр не будет удален, как вы могли себе представить.

Ответ 6

Второй способ - это просто синтаксический сахар для настройки свойств вручную:

Person p = new Person();
p.Name = "name";
p.Age = 24;

Вы также не зависите от конструктора, который может не инициализировать все свойства, которые вы хотите установить.

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

Ответ 7

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

Всегда должен быть конструктор с минимальными требованиями.

Я бы использовал только инициализаторы объектов для типов, для которых не требуется создание каких-либо свойств. Следовательно, конструктор по умолчанию.

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

Но я не думаю, что очень важно, чтобы вы могли создать Человека без имени.

Ответ 8

Мои основные соображения по этому вопросу: 1) сколько данных будет иметь экземпляр объекта при создании объекта и 2) как инкапсулирован должен быть класс? Если после установки свойства не должны меняться (по крайней мере, из-за каких-либо внешних объектов), я бы использовал конструктор, поскольку конструктор может устанавливать любые свойства только для чтения, а также любые свойства чтения/записи.

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

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

Ответ 9

Для настроек свойств вручную они должны быть объявлены общедоступными, и вы можете захотеть, чтобы члены класса были закрытыми. В этом случае конструктор - это способ пойти или написать методы, чтобы получить/установить их или использовать аксессор.

Ответ 10

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

Ответ 11

Реальная проблема возникает, когда вы передаете объект через уровни/слои. Например, вы создаете объект человека и проходите через веб-сервис. Webservice в некоторой точке пытается десериализовать и пытается создать экземпляр, а затем вы можете получить сообщение об ошибке, если для конструкторов требуется параметр! поскольку веб-службы сначала создают объект, а затем присваивают значения.

Таким образом, я бы предпочел беззадачный contructor, если это datamodel (тип POCO), который должен пройти через уровни.

По другим причинам параметр contructor является лучшим способом (для обязательных полей). Особенно при предоставлении класса как итератора внешним объектам или сборкам.