Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
906
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Список или BusinessObjectCollection?
До появления универсальных моделей C# все кодировали коллекции для своих бизнес-объектов, создавая базу коллекций, реализующую IEnumerable
IE:
public class CollectionBase : IEnumerable
и тогда они получат свои коллекции бизнес-объектов из этого.
public class BusinessObjectCollection : CollectionBase
Теперь с общим классом списка, кто-нибудь просто использует это вместо этого? Я обнаружил, что использую компромисс двух методов:
public class BusinessObjectCollection : List<BusinessObject>
Я делаю это, потому что мне нравится иметь строго типизированные имена, а не просто передавать списки.
Каков ваш подход?
Обычно я просто использую список напрямую, если только по какой-то причине мне не нужно инкапсулировать структуру данных и предоставить ограниченное подмножество ее функциональных возможностей. Это происходит главным образом потому, что если у меня нет особой потребности в инкапсуляции, то это просто пустая трата времени.
Однако с помощью функции aggregate initializes в C# 3.0 есть некоторые новые ситуации, в которых я бы рекомендовал использовать настроенные классы коллекций.
В принципе, C# 3.0 позволяет любому классу, который реализует IEnumerable и имеет метод Add, использовать новый синтаксис инициализатора aggregate. Например, поскольку словарь определяет метод Add (K key, V value), можно инициализировать словарь с помощью этого синтаксиса:
var d = new Dictionary<string, int>
{
{"hello", 0},
{"the answer to life the universe and everything is:", 42}
};
Самое замечательное в этой функции то, что она работает для методов add с любым количеством аргументов. Например, учитывая эту коллекцию:
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> напрямую.
Рекомендуется , чтобы в общественных местах API не использовали List<T>,, а использовали Collection<T>
Но если ты наследуешь от него, то все должно быть в порядке, афаик.
Я предпочитаю просто использовать List<BusinessObject> . Typedefing это просто добавляет ненужный шаблонный код в код. List<BusinessObject> -это определенный тип, это не просто какой-то объект List , поэтому он все еще строго типизирован.
Что еще более важно, объявление чего-то List<BusinessObject> облегчает каждому, кто читает код, чтобы сказать, с какими типами они имеют дело, им не нужно искать, чтобы выяснить, что такое BusinessObjectCollection , а затем помнить, что это всего лишь список. При определении типа вам придется требовать согласованного (повторного)соглашения об именовании, которому все должны следовать, чтобы оно имело смысл.
Я ходил туда и обратно по 2 вариантам:
public class BusinessObjectCollection : List<BusinessObject> {}
или методы, которые просто делают следующее:
public IEnumerable<BusinessObject> GetBusinessObjects();
Преимущества первого подхода заключаются в том, что вы можете изменить базовое хранилище данных, не связываясь с сигнатурами методов. К сожалению, если вы наследуете от типа коллекции, который удаляет метод из предыдущей реализации, то вам придется иметь дело с этими ситуациями на протяжении всего кода.
Используйте тип List<BusinessObject> , где вы должны объявить список из них. Однако,
если вы возвращаете список BusinessObject, рассмотрите возможность возврата IEnumerable<T>, IList<T> или ReadOnlyCollection<T> - т. е. верните самый слабый возможный контракт, который удовлетворяет клиента.
Там, где вы хотите "add custom code" к списку, методы расширения кода на типе списка. Опять же, приложите эти методы к самому слабому возможному контракту, например:
public static int SomeCount(this IEnumerable<BusinessObject> someList)
Конечно, вы не можете и не должны добавлять состояние с помощью методов расширения, поэтому, если вам нужно добавить новое свойство и поле за ним, используйте подкласс или, лучше, класс-оболочку для хранения этого.
Вероятно, вам следует избегать создания своей собственной коллекции для этой цели. Довольно часто требуется несколько раз изменить тип структуры данных во время рефакторинга или при добавлении новых функций. При вашем подходе вы получите отдельный класс для BusinessObjectList, BusinessObjectDictionary, BusinessObjectTree и т. д.
Я действительно не вижу никакого смысла в создании этого класса только потому, что имя класса более читаемо. Да, синтаксис угловых скобок довольно уродлив, но он стандартен в C++, C# и Java, так что даже если вы не пишете код, который использует его, вы будете постоянно сталкиваться с ним.
Вы можете использовать и то, и другое. Для лени - я имею в виду продуктивность-список является очень полезным классом, он также "comprehensive" и откровенно полон YANGNI членов. В сочетании с разумным аргументом / рекомендацией, выдвинутым в статье MSDN , уже связанной с выставлением списка в качестве публичного члена, я предпочитаю путь "third":
Лично я использую шаблон декоратора, чтобы выставить только то, что мне нужно из списка, т. е.:
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 или more likley для perf использовать коллекцию или набор пар значений ключей.
6 из 1, полдюжины других
В любом случае это одно и то же. Я делаю это только тогда, когда у меня есть причина добавить пользовательский код в BusinessObjectCollection.
С его помощью методы load возвращают список, что позволяет мне написать больше кода в общем универсальном классе и заставить его просто работать. Например, метод загрузки.
Как заметил кто-то еще, рекомендуется не выставлять список публично, и FxCop будет ныть, если вы это сделаете. Это включает в себя наследование от списка as in:
public MyTypeCollection : List<MyType>
В большинстве случаев public APIs будет выставлять IList (или ICollection, или IEnumerable) соответственно.
В тех случаях, когда вы хотите иметь свою собственную пользовательскую коллекцию, вы можете сохранить FxCop тихо, наследовав от коллекции вместо списка.
Если вы решили создать свой собственный класс коллекции, вы должны проверить типы в пространстве имен System.Collections.ObjectModel .
Пространство имен определяет базовые классы, где предназначены, чтобы сделать его проще для разработчиков для создания пользовательских коллекций.
Я обычно делаю это со своей собственной коллекцией, если хочу защитить доступ к фактическому списку. Когда вы пишете бизнес-объекты, скорее всего, вам нужен крюк, чтобы узнать, является ли ваш объект added/removed, в таком смысле, что я думаю, что BOCollection-лучшая идея. Конечно, если это не требуется, список будет более легким. Кроме того, вы можете проверить использование IList для предоставления дополнительного интерфейса абстракции, если вам нужно какое-то проксирование (например, поддельная коллекция запускает ленивую загрузку из базы данных)
Но... почему бы не рассмотреть Castle ActiveRecord или любой другой зрелый фреймворк ORM? :)
Я бы так и сделал:
using BusinessObjectCollection = List<BusinessObject>;
Это просто создает псевдоним, а не совершенно новый тип. Я предпочитаю его прямому использованию List<BusinessObject>, потому что он позволяет мне свободно изменять базовую структуру коллекции в какой-то момент в будущем без изменения кода, который ее использует (при условии, что я предоставляю те же свойства и методы).