Я бачив, як вони використовуються багато в чому однаково, і я переживаю, що збираюся піти шляхом дизайну, який є незворотним, якщо я цього не зрозумію краще. Крім того, я використовую .NET.
Я бачив, як вони використовуються багато в чому однаково, і я переживаю, що збираюся піти шляхом дизайну, який є незворотним, якщо я цього не зрозумію краще. Крім того, я використовую .NET.
Відповіді:
Collection<T>
це настроювана обгортка навколо IList<T>
. Хоча IList<T>
це не герметично, воно не надає жодних точок налаштування. Collection<T>
Методи '' за замовчуванням делеговані стандартним IList<T>
методам, але їх можна легко замінити, щоб зробити те, що ви хочете. Також можна підключати події всередині aCollection<T>
що, на мою думку, неможливо зробити за допомогою IList.
Коротше кажучи, набагато простіше продовжити його після факту, що потенційно може означати набагато менше рефакторингу.
IList
, IList<T>
, і List<T>
т.д. Коротше кажучи, ви не маєте жодного уявлення , чи буде це назвати. Поліморфізм це виправляє.
ObservableCollection<T>
як приклад, коли методи замінені, щоб повідомляти про зміни.
У C # є три концепції представлення мішка об’єктів. У порядку збільшення функцій вони:
Численні немає порядку. Ви не можете додавати або видаляти елементи з набору. Ви навіть не можете отримати кількість предметів у наборі. Це суворо дозволяє вам отримати доступ до кожного предмета в наборі, один за одним.
Колекція - це модифікований набір. Ви можете додавати та видаляти об'єкти з набору, ви також можете отримати кількість елементів у наборі. Але порядку все ще немає, а оскільки його немає: немає можливості отримати доступ до елемента за індексом, а також немає способу сортування.
Список - це впорядкований набір об’єктів. Ви можете сортувати список, отримувати доступ до елементів за індексом, видаляти елементи за індексом.
Насправді, розглядаючи інтерфейси для них, вони будують один на одного:
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>
- це сумка, в якій вам заборонено отримувати доступ до предметів за індексом ( ICollection
); але ви можете довільно додавати та вилучати елементи з колекціїSynchronizedCollection<T>
у впорядкованій колекції, де ви можете додавати / видаляти елементи за індексомВи можете легко змінити:
IEnumerable<User> users = new SynchronizedCollection<User>();
SaveEveryUser(users);
Виберіть потрібну вам концепцію , а потім скористайтесь відповідним класом.
ICollection<T>
та IList<T>
. Різні конкретні реалізації можуть поводитися по-різному. Наприклад, якщо ви отримуєте доступ до List<T>
через його IEnumerable<T>
інтерфейс, то у вас немає можливості додавати, видаляти, сортувати або підраховувати елементи у списку.
List<T>
призначений для внутрішнього використання в коді програми. Вам слід уникати написання загальнодоступних API, які приймають або повертають List<T>
( натомість використовуйте суперклас або інтерфейс колекції).
Collection<T>
обслуговує базовий клас для спеціальних колекцій (хоча його можна використовувати безпосередньо).
Подумайте про використання Collection<T>
у своєму коді, якщо немає певних особливостей, List<T>
які вам потрібні.
Вищезазначені лише рекомендації.
[Адаптовано з: Керівних принципів проектування, друге видання]
Dictionary<string, List<string>>
повернення a List<string>
- це нормально, оскільки стан словника інкапсулює лише ідентифікатори списків, а не їх вміст.
List<T>
є дуже часто зустрічається контейнером, оскільки він настільки універсальний (з безліччю зручних методів, як Sort
, Find
тощо) - але не має точок розширення, якщо ви хочете замінити будь-яку поведінку (наприклад, позначте елементи на вставці).
Collection<T>
є обгорткою навколо будь-якого IList<T>
(за замовчуванням List<T>
) - він має точки розширення ( virtual
методи), але не так багато методів підтримки, як Find
. Через опосередкованість він трохи повільніший, ніж List<T>
, але не набагато.
З допомогою LINQ, додаткові методи в List<T>
стає менш важливим, так як LINQ до об'єктів , як правило , надати їм все одно ... наприклад 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<>
майже вдвічі швидше.
Редагувати
Я не можу зрозуміти, чому люди голосують проти цього. Як на моїй робочій машині, так і на домашній машині, код <> є швидшим на 80%.
Список представляє колекцію, де порядок предметів важливий. Він також підтримує методи сортування та пошуку. Збір - це більш загальна структура даних, яка робить менше припущень щодо даних, а також підтримує менше методів їх маніпулювання. Якщо ви хочете розкрити власну структуру даних, вам, ймовірно, слід розширити колекцію. Якщо вам потрібно маніпулювати даними без викриття структури даних, список, мабуть, є найбільш зручним способом.
Це одне з тих питань міської школи. Колекція Т - це свого роду реферат; може бути реалізація за замовчуванням (я не хлопець .net / c #), але колекція матиме основні операції, такі як додавання, видалення, ітерація тощо.
Список T передбачає деякі особливості щодо цих операцій: додавання має займати постійний час, видалення має займати час, пропорційний кількості елементів, getfirst повинен мати постійний час. Загалом, Список є різновидом Колекції, але Колекція не обов’язково є різновидом Списку.
Ганзельман говорить : " Collection<T>
схожий на список, і він навіть має List<T>
внутрішній характер. КОЖНИЙ єдиний метод делегує внутрішній List<T>
. Він включає захищену властивість, яка виставляє" List<T>
.
EDIT: Collection<T>
не існує у System.Generic.Collections .NET 3.5. Якщо ви переходите з .NET 2.0 на 3.5, вам потрібно буде змінити код, якщо ви використовуєте багато Collection<T>
об’єктів, якщо я не пропускаю щось очевидне ...
EDIT 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)" (коли "Ємність" перевищена), тоді як Collection (Of T) .Add - це завжди "операція O (1)". Це було б зрозуміло, якщо List реалізується за допомогою масиву, а колекція пов’язаного списку. Однак, якби це було так, можна було б очікувати, що Collection (Of T). Елемент буде "операцією O (n)". Але - це - ні !?! Collection (Of T) .Item - це "операція O (1)", як і List (Of T).
На додачу до цього, пост "tuinstoel" "29 грудня 2008 року о 22:31" над тестами швидкості претензій показує Список (З Т). Додайте, щоб він був швидшим за Збір (З Т). Лонга та Струни. Хоча я отримав лише ~ 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() *