Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 23, 2022 01:38 am GMT

Differences between .NET Collection Interfaces

If youre anything like most new .NET developers youve probably seen IEnumerable<T>, IList<T>, and maybe even ICollection<T> around. If youre anything like most people, youve probably found these interfaces confusing and been unsure which one to use when.

These interfaces are everywhere. For example, if you were to look at the List<T> classs implementation in modern .NET youd see it implements the following interfaces (among others):

  • IList<T>
  • ICollection<T>
  • IReadOnlyList<T>
  • IReadOnlyCollection<T>
  • IEnumerable<T>

Each one of these interfaces has a point, and each one is slightly different. However, many of these interfaces can be intimidating the first time you encounter them.

In this article well explore these common .NET interfaces, what they provide, and when you might choose to use each one.

Note: There are also the older non-generic interfaces of IEnumerable and IList. For the purposes of this article well focus instead on generic collection interfaces since these are more commonly used in modern .NET.

Why not just use List<T>?

When I teach my students about IEnumerable, I usually see eyes gloss over from the abstractness of the concept and the foreignness of the word enumerable. A modest chunk of my students start panicking and wonder if they can scurry back to the safety of just working with List<T> and pretend that interfaces arent there.

The short answer is this: You can ignore collection interfaces some of the time.

However, sometimes you have to work with these interfaces when others provide them to you, and sometimes its better to work with these interfaces instead of concrete types.

To explore this, lets take a look at this simple example below:

private List<User> _users = new();public List<User> Users{   get   {      return _users;   }}

Here it looks like we have a properly encapsulated List of User objects in the _usersfield. However, upon closer examination, there are a few problems:

First, by returning aList<User> we invite others to store the result of this call in List<User> variables or properties. This is fine for now, but if we ever change the type of collection were returning, our callers will need to update as well.

Secondly, by returning aList<User>, we give calling methods full access to the methods on that List object, including Add, Remove, and Sort. Worse, these methods will work and update the same Listour code is using in its _users field.

This violates encapsulation and may result in inconsistent state within the class due to changes to the internal state of the class coming from outside of the class in unintended ways.

Alternatively, if this didnt actually modify the class, but the caller still thought they could use the Add, Remove, or Sortmethods, they are now confused and frustrated because our design didnt indicate to them that they couldnt do this.

While these problems arent typically catastrophic, itd be better to avoid them if we can, which is where .NET collection interfaces come into play.

Common .NET Collection Interfaces

Because a picture can be far more efficient than entire sections, Ive summarized these five interfaces in this comparison matrix:

A comparison of common .NET collection interfaces as detailed below.

In the sections below well explore each one of these five interfaces and when to use each one.

IEnumerable<T>

IEnumerable<T> is a foundational interface in .NET that simply means that something can be looped over in a foreachstatement.

IEnumerable<T> is supported by List<T>, arrays, and almost any other collection type in .NET.

Thats about all you need to know about IEnumerable<T>, but if youd like a few more details, read on to learn about IEnumerator<T> as well.

IEnumerable<T> internally works by providing a GetEnumerator method that returns an IEnumerator<T> object.

This IEnumerator<T> provides ways to:

  • Get the current item (if one is present)
  • Move to the next item
  • Reset back to the first item

These three capabilities power any collection type that can be looped over.

ICollection<T>

ICollection<T> allows you to manage collections of items. All ICollection<T>s are also IEnumerable<T>.

Using ICollection<T> you can:

  • Get a Countof the number of items in a collection
  • See if a collection Containssomething
  • Modify the collection by Add, Remove, and Clearmethods
  • Copy the collection to an array
  • Determine if the collection is read only

Notably, ICollection<T> does not include array indexers in the interface, so you cannot use an indexer to get an item out of a collection by its index.

ICollection<T> is a great choice if you need to add and remove things from a collection as well as loop over it, but you dont need to use an indexer.

IList<T>

IList<T> is an extremely powerful and common ordered collection interface in .NET.

IList<T>s all implement both ICollection<T> and IEnumerable<T> but add the ability to work with indexes.

Specifically, IList<T> adds the following capabilities:

  • A collection indexer that lets you use syntax like int number = myList[0];
  • Allows you to find the IndexOfan item in the list
  • Insertitems at a specific index
  • RemoveAta specific index

If your collection is ordered and has specific indexes and you want others to take full advantage of them, IList<T> is a great choice.

IReadOnlyCollection<T>

IReadOnlyCollection<T> is a rarer interface to see, but it is essentially a version of IEnumerable<T> that also has a Count of items.

You can also think about IReadOnlyCollection<T> as a version of Collection<T> that removes ways of modifying the items.

All IReadOnlyCollection<T>s are also IEnumerable<T>.

IReadOnlyCollection<T> is a good choice if you want to return a collection but dont want to expose ways of manipulating it through the interface.

IReadOnlyList<T>

IReadOnlyList<T> is an extension of IReadOnlyCollection<T> but adds an indexer so that you can get values out of the collection by an index. Otherwise, IReadOnlyList<T> is functionally identical to IReadOnlyCollection<T>.

Securing against Casting

You may now be thinking that using an IReadOnlyList<T> or IReadOnlyCollection<T> protects you from others modifying your code.

However, that actually may not be fully true.

Lets revisit our example from earlier, but take advantage of IReadOnlyList<T>:

private List<User> _users = new();public IReadOnlyList<User> Users{   get   {      return _users;   }}

Here the class can use a full List<User> internally but only expose IReadOnlyList<User> to external callers.

This stops callers from doing the following:

// Wouldn't work since Users is an IReadOnlyListmyObject.Users.Add(new User("Matt Eland"));

However, since the actual object being returned above is still a List<User>, savvy callers may notice this and cast the result to a List<User> and then interact with it in a way you didnt intend:

// Cast the result of the Users property to a List<User>List<User> users = (List<User>)myObject.Users;// This worksusers. Add(new User("Matt Eland"));

Because of this, its a good idea to secure the items you intend to be read only by calling either ToList() or AsReadOnly() on them using LINQ to create a separate collection when returning values as shown below:

private List<User> _users = new();public IReadOnlyList<User> Users{   get   {      return _users.AsReadOnly();   }}

Conclusion

While its certainly possible to write code that just returns Lists or other concrete types, using the appropriate .NET collection interface can help your code shine.

Using the right interface lets others see your intent, helps you properly encapsulate your classes, and gives you flexibility to change collection types in a class without impacting callers.


Original Link: https://dev.to/integerman/differences-between-net-collection-interfaces-g3i

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To