I've seen them used in a lot of the same ways, and I am worried I'm about to go down a path in design that is irreversible if I don't understand this better. Also, I am using .NET.
In List, data is in particular order. In Set, it can not contain the same data twice. In Collection, it just stores data with no particular order and can contain duplicate data.
A Collection is just that: a collection of items. You can add stuff, remove stuff, iterate over stuff and query how much stuff is in there. A List is one sub interface which defines an ordered Collection, other sub interfaces are Queue which typically will store elements ready for processing (e.g. stack).
It depends on what guarantees you want to provide the user. If the data is sequential such that the order of the elements matter and you are allowing duplicates, then use a list. If order of elements does not matter and duplicates may or may not be allowed, then use a collection.
The main difference between IEnumerable and List in C# is that IEnumerable is an interface, while List is a concrete class. Moreover, IEnumerable is read-only and List is not.
In C#, there are three concepts for representing a bag of objects. In order of increasing features, they are:
Enumerable has no order. You cannot add or remove items from the set. You cannot even get a count of items in the set. It strictly lets you access each item in the set, one after the other.
Collection is a modifiable set. You can add and remove objects from the set, you can also get the count of items in the set. But there still is no order, and because there is no order: no way to access an item by index, nor is there any way to sort.
List is an ordered set of objects. You can sort the list, access items by index, remove items by index.
In fact, when looking at the interfaces for these, they build on one another:
interface IEnumerable<T>
GetEnumeration<T>
interface ICollection<T> : IEnumerable<T>
Add
Remove
Clear
Count
interface IList<T> : ICollection<T>
Insert
IndexOf
RemoveAt
When declaring variables, or method parameters, you should choose to use
based on what conceptually you need to do with the set of objects.
If you just need to be able to do something to every object in a list, then you only need IEnumerable
:
void SaveEveryUser(IEnumerable<User> users) { for User u in users ... }
You don't care if the Users are kept in a List<T>
, Collection<T>
, Array<T>
or anything else. You only need the IEnumerable<T>
interface.
If you need to be able to add, remove, or count the items in a set, then use a Collection:
ICollection<User> users = new Collection<User>(); users.Add(new User());
If you care about a sort order, and need the order to be correct, then use a List:
IList<User> users = FetchUsers(db);
In chart form:
| 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 index | | | X | | Getting index of item | | | X |
The List<T>
and Collection<T>
in System.Collections.Generic
are two classes that implement these interfaces; but they aren't the only classes:
ConcurrentBag<T>
is an ordered bag of objects (IEnumerable<T>
)LinkedList<T>
is a bag where you are not allowed to access items by index (ICollection
); but you can arbitrarily add and remove items from the collectionSynchronizedCollection<T>
is an ordered collection, where you can add/remove items by indexSo you can easily change:
IEnumerable<User> users = new SynchronizedCollection<User>(); SaveEveryUser(users);
Choose the concept you need, then use the matching class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With