Список <BusinessObject> или BusinessObjectCollection?

До генерации С# все будут собирать коллекции для своих бизнес-объектов, создавая базу данных, которая реализовала IEnumerable

IE:

public class CollectionBase : IEnumerable

а затем извлечет их коллекции бизнес-объектов из этого.

public class BusinessObjectCollection : CollectionBase

Теперь с общим классом списка, кто-нибудь просто использует это вместо этого? Я обнаружил, что я использую компромисс двух методов:

public class BusinessObjectCollection : List<BusinessObject>

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

Что такое ваш подход?

Ответ 1

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

Однако, с функцией агрегации инициализации в С# 3.0, есть несколько новых ситуаций, в которых я буду выступать за использование настраиваемых классов сбора.

В принципе, С# 3.0 позволяет любому классу, реализующему IEnumerable, и имеет метод Add для использования нового синтаксиса инициализатора агрегата. Например, поскольку словарь определяет метод Add (К-ключ, значение V), можно инициализировать словарь с помощью этого синтаксиса:

var d = new Dictionary<string, int>
{
    {"hello", 0},
    {"the answer to life the universe and everything is:", 42}
};

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

class c1 : IEnumerable
{
    void Add(int x1, int x2, int x3)
    {
        //...
    }

    //...
}

можно было бы инициализировать его так:

var x = new c1
{
    {1,2,3},
    {4,5,6}
}

Это может быть действительно полезно, если вам нужно создать статические таблицы сложных объектов. Например, если вы просто использовали List<Customer> и вы хотели создать статический список объектов клиента, вам нужно было бы создать его так:

var x = new List<Customer>
{
    new Customer("Scott Wisniewski", "555-555-5555", "Seattle", "WA"),
    new Customer("John Doe", "555-555-1234", "Los Angeles", "CA"),
    new Customer("Michael Scott", "555-555-8769", "Scranton PA"),
    new Customer("Ali G", "", "Staines", "UK")
}

Однако, если вы используете настраиваемую коллекцию, такую ​​как:

class CustomerList  : List<Customer>
{
    public void Add(string name, string phoneNumber, string city, string stateOrCountry)
    {
        Add(new Customer(name, phoneNumber, city, stateOrCounter));
    }
}

Затем вы можете инициализировать коллекцию с помощью этого синтаксиса:

var customers = new CustomerList
{
    {"Scott Wisniewski", "555-555-5555", "Seattle", "WA"},
    {"John Doe", "555-555-1234", "Los Angeles", "CA"},
    {"Michael Scott", "555-555-8769", "Scranton PA"},
    {"Ali G", "", "Staines", "UK"}
}

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

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

Мой совет будет заключаться в том, что если вам нужно определить статический набор объектов или инкапсулировать интерфейс коллекции, создайте собственный класс коллекции. В противном случае я просто использовал бы List<T> напрямую.

Ответ 2

рекомендуется, чтобы в публичном API не использовать List <T> , но использовать Collection <T>

Если вы наследуете его, но вы должны быть в порядке, afaik.

Ответ 3

Я предпочитаю использовать List<BusinessObject>. Типизация просто добавляет ненужный шаблон в код. List<BusinessObject> - это особый тип, это не только любой объект List, поэтому он все еще строго типизирован.

Что еще более важно, объявление чего-то List<BusinessObject> упрощает чтение каждым кодом кода, с какими типами они имеют дело, им не нужно искать, что такое BusinessObjectCollection, а затем помнить, что это просто список. При помощи typedefing вам понадобится согласованное (повторное) соглашение об именах, которое каждый должен соблюдать, чтобы это имело смысл.

Ответ 4

Я собираюсь в двух вариантах:

public class BusinessObjectCollection : List<BusinessObject> {}

или методы, которые просто выполняют следующие действия:

public IEnumerable<BusinessObject> GetBusinessObjects();

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

Ответ 5

Используйте тип List<BusinessObject>, где вы должны объявить их список. Однако, где вы возвращаете список BusinessObject, подумайте о возврате IEnumerable<T>, IList<T> или ReadOnlyCollection<T> - т.е. верните самый слабый возможный контракт, который удовлетворяет клиента.

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

public static int SomeCount(this IEnumerable<BusinessObject> someList)

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

Ответ 6

Я делаю то же самое, что и вы, Джонатан... просто наследуем от List<T>. Вы получаете лучшее из обоих миров. Но я обычно делаю это только тогда, когда есть какое-то значение для добавления, например, добавление метода LoadAll() или что-то еще.

Ответ 7

Вероятно, вам не следует создавать собственную коллекцию для этой цели. Очень часто хочется изменить тип структуры данных несколько раз во время рефакторинга или при добавлении новых функций. С вашим подходом вы получите отдельный класс для BusinessObjectList, BusinessObjectDictionary, BusinessObjectTree и т.д.

Я действительно не вижу никакого значения при создании этого класса только потому, что имя класса более читаемо. Да, синтаксис угловой скобки является довольно уродливым, но он стандартен в С++, С# и Java, поэтому, даже если вы не пишете код, который его использует, вы будете сталкиваться с ним все время.

Ответ 8

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

Ответ 9

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

Лично я использую шаблон декоратора, чтобы показывать только то, что мне нужно из списка i.e:

public OrderItemCollection : IEnumerable<OrderItem> 
{
    private readonly List<OrderItem> _orderItems = new List<OrderItem>();

    void Add(OrderItem item)
    {
         _orderItems.Add(item)
    }

    //implement only the list members, which are required from your domain. 
    //ie. sum items, calculate weight etc...

    private IEnumerator<string> Enumerator() {
        return _orderItems.GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }    
}

Далее я бы, вероятно, выделил OrderItemCollection в IOrderItemCollection, чтобы в будущем я мог поменять свою реализацию IOrderItemCollection (я могу предпочесть использовать другой внутренний перечислимый объект, такой как Collection или более likley для первоочередного использования пары ключевых значений коллекции или набора.

Ответ 10

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

Ответ 11

6 из 1, половина десятка другого

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

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

Ответ 12

Как указывал кто-то другой, рекомендуется не публиковать публичный список, а FxCop будет петь, если вы это сделаете. Это включает в себя наследование из списка как:

public MyTypeCollection : List<MyType>

В большинстве случаев публичные API-интерфейсы будут подвергать IList (или ICollection или IEnumerable) соответствующим образом.

В тех случаях, когда вы хотите создать собственную коллекцию, вы можете оставить FxCop тихим, наследуя от Collection вместо List.

Ответ 13

Если вы решили создать свой собственный класс коллекции, вы должны проверить типы в System.Collections.ObjectModel Namespace.

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

Ответ 14

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

Но... почему бы не рассмотреть Castle ActiveRecord или любую другую зрелую структуру ORM?:)

Ответ 15

В большинстве случаев я просто перехожу со способом List, так как он дает мне всю необходимую мне функциональность в 90% случаев, и когда требуется что-то "лишнее", я наследую его и код этот дополнительный бит.

Ответ 16

Я бы сделал это:

using BusinessObjectCollection = List<BusinessObject>;

Это просто создает псевдоним, а не совершенно новый тип. Я предпочитаю использовать List <BusinessObject> напрямую, потому что он оставляет мне возможность изменить базовую структуру коллекции в какой-то момент в будущем, не меняя код, который ее использует (пока я предоставляю те же свойства и методы).

Ответ 17

попробуйте следующее:

System.Collections.ObjectModel.Collection<BusinessObject>

нет необходимости реализовывать базовый метод, например CollectionBase do

Ответ 18

это способ:

возвратить массивы, принять IEnumerable<T>

=)