Я видел, как они использовались одинаково, и я беспокоюсь, что собираюсь пойти по пути в дизайне, который необратим, если я не пойму это лучше. Кроме того, я использую .NET.
Я видел, как они использовались одинаково, и я беспокоюсь, что собираюсь пойти по пути в дизайне, который необратим, если я не пойму это лучше. Кроме того, я использую .NET.
Ответы:
Collection<T>
- это настраиваемая оболочка IList<T>
. Хотя IList<T>
он не запечатан, он не предоставляет никаких точек настройки. Collection<T>
методы по умолчанию делегированы стандартным IList<T>
методам, но их можно легко переопределить для выполнения того, что вы хотите. Также возможно подключать события внутри a, Collection<T>
которые, я не верю, можно сделать с помощью IList.
Короче говоря, гораздо проще расширить его постфактум, что потенциально может означать намного меньше рефакторинга.
IList
, IList<T>
, и List<T>
т.д. Короче говоря, вы не имеете ни малейшего представления , будет ли это назвать. Полиморфизм исправляет это.
ObservableCollection<T>
пример, в котором методы переопределяются для уведомления об изменениях.
В C # существует три концепции представления набора объектов. В порядке увеличения характеристик это:
Enumerable не имеет порядка. Вы не можете добавлять или удалять предметы из набора. Вы даже не можете подсчитать количество предметов в наборе. Это строго позволяет вам получить доступ к каждому элементу в наборе, один за другим.
Коллекция - это изменяемый набор. Вы можете добавлять и удалять объекты из набора, вы также можете получить количество предметов в наборе. Но по-прежнему нет порядка, и потому что нет порядка: нет возможности получить доступ к элементу по индексу, и нет никакого способа сортировки.
Список - это упорядоченный набор объектов. Вы можете отсортировать список, получить доступ к элементам по индексу, удалить элементы по индексу.
Фактически, если посмотреть на их интерфейсы, они основаны друг на друге:
interface IEnumerable<T>
GetEnumeration<T>
interface ICollection<T> : IEnumerable<T>
Add
Remove
Clear
Count
interface IList<T> = ICollection<T>
Insert
IndexOf
RemoveAt
При объявлении переменных или параметров метода вы должны использовать
Исходя из концептуально, что нужно делать с набором объектов.
Если вам просто нужно иметь возможность что-то делать с каждым объектом в списке, вам нужно только IEnumerable
:
void SaveEveryUser(IEnumerable<User> users)
{
for User u in users
...
}
Вам не все равно , если пользователи будут храниться в List<T>
, Collection<T>
, Array<T>
или что - нибудь еще. Вам нужен только IEnumerable<T>
интерфейс.
Если вам нужно иметь возможность добавлять, удалять или подсчитывать элементы в наборе, используйте коллекцию :
ICollection<User> users = new Collection<User>();
users.Add(new User());
Если вы заботитесь о порядке сортировки и хотите, чтобы порядок был правильным, используйте список :
IList<User> users = FetchUsers(db);
В виде диаграммы:
| Feature | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| Enumerating items | X | X | X |
| | | | |
| Adding items | | X | X |
| Removing items | | X | X |
| Count of items | | X | X |
| | | | |
| Accessing by index | | | X |
| Removing by indexx | | | X |
| Getting index of item | | | X |
List<T>
И Collection<T>
в System.Collections.Generic
два класса , которые реализуют эти интерфейсы; но это не единственные классы:
ConcurrentBag<T>
это заказанный мешок предметов ( IEnumerable<T>
)LinkedList<T>
это сумка, в которой вам не разрешен доступ к элементам с помощью index ( ICollection
); но вы можете произвольно добавлять и удалять элементы из коллекцииSynchronizedCollection<T>
в упорядоченной коллекции, где вы можете добавлять / удалять элементы по индексуТаким образом, вы можете легко изменить:
IEnumerable<User> users = new SynchronizedCollection<User>();
SaveEveryUser(users);
Выберите нужную вам концепцию , затем используйте соответствующий класс.
ICollection<T>
и IList<T>
. Различные конкретные реализации могут вести себя по-разному. Например, если вы получаете доступ к a List<T>
через его IEnumerable<T>
интерфейс, то у вас нет возможности добавлять, удалять, сортировать или подсчитывать элементы в списке.
List<T>
предназначен для внутреннего использования в коде приложения. Вам следует избегать написания общедоступных API, которые принимают или возвращают List<T>
(рассмотрите возможность использования вместо этого суперкласса или интерфейса коллекции).
Collection<T>
служит базовым классом для пользовательских коллекций (хотя его можно использовать напрямую).
Рассмотрите возможность использования Collection<T>
в своем коде, если нет конкретных функций, List<T>
которые вам нужны.
Выше приведены лишь рекомендации.
[Адаптировано из: Руководство по разработке каркаса, второе издание]
Dictionary<string, List<string>>
для возврата List<string>
- это нормально, поскольку состояние словаря инкапсулирует только идентификаторы списков в нем, а не их содержимое.
List<T>
- это очень часто встречающийся контейнер, потому что он очень универсален (с множеством удобных методов, таких как Sort
, Find
и т. д.), но не имеет точек расширения, если вы хотите переопределить какое-либо поведение (например, отметьте элементы на вставке).
Collection<T>
является оболочкой для любого IList<T>
(по умолчанию List<T>
) - он имеет точки ( virtual
методы) расширения , но не так много методов поддержки, как Find
. Из-за косвенного обращения он немного медленнее List<T>
, но ненамного.
С LINQ дополнительные методы List<T>
становятся менее важными, поскольку LINQ-to-Objects имеет тенденцию предоставлять их в любом случае ... например First(pred)
, OrderBy(...)
и т. Д.
Список быстрее.
Например
private void button1_Click(object sender, EventArgs e)
{
Collection<long> c = new Collection<long>();
Stopwatch s = new Stopwatch();
s.Start();
for (long i = 0; i <= 10000000; i++)
{
c.Add(i);
}
s.Stop();
MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString());
List<long> l = new List<long>();
Stopwatch s2 = new Stopwatch();
s2.Start();
for (long i = 0; i <= 10000000; i++)
{
l.Add(i);
}
s2.Stop();
MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString());
}
на моей машине List<>
почти в два раза быстрее.
редактировать
Я не могу понять, почему люди голосуют против этого. И на моей рабочей машине, и на моей домашней машине код List <> на 80% быстрее.
Список представляет собой коллекцию, в которой важен порядок элементов. Он также поддерживает методы сортировки и поиска. Коллекция - это более общая структура данных, которая делает меньше предположений о данных, а также поддерживает меньше методов для управления ими. Если вы хотите предоставить настраиваемую структуру данных, вам, вероятно, следует расширить коллекцию. Если вам нужно манипулировать данными без раскрытия структуры данных, список, вероятно, будет более удобным способом.
Это один из тех вопросов аспирантуры. Коллекция T - своего рода абстрактная; может быть реализация по умолчанию (я не парень .net / c #), но коллекция будет иметь базовые операции, такие как добавление, удаление, итерация и т. д.
Список T подразумевает некоторые особенности этих операций: добавление должно занимать постоянное время, удаление должно занимать время, пропорциональное количеству элементов, getfirst должно быть постоянным временем. В общем, список является разновидностью коллекции, но коллекция не обязательно является разновидностью списка.
Хансельман говорит : « Collection<T>
выглядит как список, и у него даже есть List<T>
внутренний. КАЖДЫЙ единственный метод делегирует внутреннему List<T>
. Он включает защищенное свойство, которое предоставляет List<T>
.»
РЕДАКТИРОВАТЬ: Collection<T>
не существует в System.Generic.Collections .NET 3.5. Если вы переходите с .NET 2.0 на 3.5, вам нужно будет изменить код, если вы используете много Collection<T>
объектов, если я не упускаю что-то очевидное ...
РЕДАКТИРОВАТЬ 2: Collection<T>
теперь находится в пространстве имен System.Collections.ObjectModel в .NET 3.5. В файле справки сказано следующее:
«Пространство имен System.Collections.ObjectModel содержит классы, которые могут использоваться как коллекции в объектной модели многоразовой библиотеки. Используйте эти классы, когда свойства или методы возвращают коллекции».
Все эти интерфейсы являются наследниками IEnumerable
, и вы должны убедиться, что понимаете. Этот интерфейс в основном позволяет использовать класс в операторе foreach (в C #).
ICollection
- это самый простой из перечисленных вами интерфейсов. Это перечислимый интерфейс, который поддерживает a, Count
и на этом все.IList
есть все, что ICollection
есть, но он также поддерживает добавление и удаление элементов, получение элементов по индексу и т. д. Это наиболее часто используемый интерфейс для «списков объектов», который, насколько мне известно, расплывчатый.IQueryable
- это перечисляемый интерфейс, поддерживающий LINQ. Вы всегда можете создать IQueryable
из списка IList и использовать LINQ to Objects, но вы также можете найти его IQueryable
для отложенного выполнения операторов SQL в LINQ to SQL и LINQ to Entities.IDictionary
это другое животное в том смысле, что это отображение уникальных ключей к значениям. Он также перечислим, поскольку вы можете перечислять пары ключ / значение, но в остальном он служит другой цели, чем другие, которые вы указали.Согласно MSDN, List (Of T) .Add - это «операция O (n)» (когда «Capacity» превышена), а Collection (Of T) .Add - всегда «операция O (1)». Это было бы понятно, если бы List был реализован с использованием массива и коллекции связанного списка. Однако, если бы это было так, можно было бы ожидать, что Collection (Of T) .Item будет «операцией O (n)». Но - это - нет !?! Collection (Of T) .Item - это «операция O (1)», как и List (Of T) .Item.
Вдобавок к этому, сообщение "tuinstoel" "29 декабря '08 в 22:31" выше утверждает, что тесты скорости показывают List (Of T) .Add, чтобы быть быстрее, чем Collection (Of T) .Add, который я воспроизвел с помощью Длинные и струнные. Хотя я получил только ~ 33% быстрее по сравнению с его заявленными 80%, согласно MSDN, должно было быть наоборот и в "n" раз!?!
Оба реализуют одни и те же интерфейсы, поэтому они будут вести себя одинаково. Возможно, они по-другому реализованы внутри, но это нужно будет проверить.
Единственные реальные различия, которые я вижу, - это пространства имен и тот факт, который Collection<T>
отмечен значком ComVisibleAttribute(false)
, поэтому код COM не может его использовать.
В дополнение к другим ответам я составил краткий обзор общих возможностей списков и коллекций. Коллекция - это ограниченное подмножество Списка:
* = присутствует
o = частично присутствует
Коллекция свойств / методов <T> Список <T>
----------------------------------------------
Add() * *
AddRange() *
AsReadOnly() *
BinarySearch() *
Capacity *
Clear() * *
Contains() * *
ConvertAll() *
CopyTo() o *
Count * *
Equals() * *
Exists() *
Find() *
FindAll() *
FindIndex() *
FindLast() *
FindLastIndex() *
ForEach() *
GetEnumerator() * *
GetHashCode() * *
GetRange() *
GetType() * *
IndexOf() o *
Insert() * *
InsertRange() *
Item() * *
LastIndexOf() *
New() o *
ReferenceEquals() * *
Remove() * *
RemoveAll() *
RemoveAt() * *
RemoveRange() *
Reverse() *
Sort() *
ToArray() *
ToString() * *
TrimExcess() *
TrueForAll() *