Есть ли необходимость инкапсулировать коллекции? - PullRequest
2 голосов
/ 08 ноября 2010

Есть ли необходимость инкапсулировать коллекции?

скажем

private List<Item> items;

public Items Items
{
    get { return this.items; }
    set { this.items= value; }
}

или просто

public List<Item> Items;

EDIT:

  • Есть ли способ привязать коллекцию, не подвергая публичного добытчика?

Ответы [ 7 ]

4 голосов
/ 08 ноября 2010

Я обычно выставляю коллекции только для чтения.Обычно нет причин назначать новую коллекцию.Я создам экземпляр коллекции один раз в конструкторе или получателе свойств.Это уменьшает вероятность ошибок нулевой ссылки.

3 голосов
/ 08 ноября 2010

Публикация коллекций - плохая идея. Хотя инкапсуляция полей важна в любом случае, коллекции еще важнее.

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

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

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

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

2 голосов
/ 08 ноября 2010

Публичные поля вообще не одобряются в мире .NET. Кроме того, возвращающий нулевые коллекции из методов или свойств также не одобряется. Поэтому я бы определенно «инкапсулировал» коллекцию.

1 голос
/ 08 ноября 2010

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

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

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

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

1 голос
/ 08 ноября 2010

Рекомендуется не разглашать сеттеры коллекционных свойств; см. это правило в MSDN. Еще лучшая практика - выставлять только интерфейс, а не конкретный тип.

class Example
{
     public Example()
     {
         this.MyList = new List<string>();
     }

     public IList<string> MyList { get; private set; }
}
1 голос
/ 08 ноября 2010

Иногда я подключаю его вот так ...

List<Item> _items;
public Items Items
{
    get 
    {
        if (_items == null) _items = new List<Items>();
        return _items;
    }
    private set { _items = value; }
}
1 голос
/ 08 ноября 2010

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

public class PotOfUnicorns
{

    private List<Item> items = new List<Item>();

    public Items Items
    {
        get { return this.items; }
        private set { this.items= value; }
    }

}
...