Стратегия инициализации экземпляра в c # - PullRequest
1 голос
/ 10 марта 2010

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

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

Каков наилучший метод?

Ответы [ 4 ]

2 голосов
/ 10 марта 2010

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

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

В определенной степени это зависит от вашей модели. Например, в ORM, который я использую, конструктор принимает один параметр; идентификатор, по которому он может загружать все остальные свойства. Было бы неприятно, если бы мне пришлось передать их все (это действительно задача ORM; настроить этот объект). Таким образом, в этом смысле вы можете утверждать, что у вас есть «недействительный» объект (свойства не установлены). Но ты ошибаешься; то, что у вас есть, это «пустой» или «пустой» объект. Это не то же самое, что недействительный.

Так что подумайте о том, что означает, что ваш объект является "недействительным". Я бы посчитал его недействительным, если бы другие методы взяли этот объект и выдавали исключение, потому что что-то не было установлено. Используйте эту логику, чтобы определить, что должно быть в конструкторе, а что может быть установлено позже (каким-либо другим процессом).

2 голосов
/ 10 марта 2010

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

Во многих случаях вам может понадобиться создать составной тип, который имеет много свойств и множество возможных конфигураций (например, System.Web.Page). Составные типы, как правило, имеют простые конструкторы, которые принимают мало или не имеют параметров, и все значения должны быть установлены через свойства. Составные типы - это высокоуровневые типы, которые состоят из факторизованных (или примитивных) типов нижнего уровня.

Факторные типы, как правило, проще, содержат меньше состояний и могут быть полностью инициализированы через свои конструкторы. Примерами факторизованных типов являются System.String и System.Int32. Эти типы очень просты и, как правило, являются строительными блоками составных типов.

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

1 голос
/ 10 марта 2010

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

При проверке вам придется проверять действительность объекта, но это довольно распространенная вещь. Что-то между строк:

public interface IValidateable {
  IEnumerable<string> Validate();
}

public class Person : IValidateable {
    public string Title { get; set; }
    public string First { get; set; }
    public string Last { get; set; }
    public Address HomeAddress { get; set; }

    public Person() {
      HomeAddress = new Address();
    }


    public IEnumerable<string> Validate() {
      var errors = new List<string>();
      if (string.IsNullOrEmpty(First))
        errors.Add("First name is required.");
      // And so on...
      return errors;
    }    
}

// Usage
var p1 = new Person();
var p2 = new Person {
    First = "Dmitriy"
  };

if (p1.Validate().Any()) {
  // Do something with invalid object
}
1 голос
/ 10 марта 2010

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

...