Skip to content

Instantly share code, notes, and snippets.

@stormwild
Last active March 28, 2023 01:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stormwild/ddb73df0330e1aea8eb3d7784184c376 to your computer and use it in GitHub Desktop.
Save stormwild/ddb73df0330e1aea8eb3d7784184c376 to your computer and use it in GitHub Desktop.

IEnumerable

IEnumerable vs IReadOnlyList

That’s by the way also true for IEnumerable itself. This interface provides only the basic functionality for working with collections (really, just iterating through them), and so if your method requires more than that, also state that requirement up front. For example, if the only thing you need out of a collection is the capability to enumerate its elements, it’s fine to use IEnumerable:

public void SomeMethod(IEnumerable<string> collection)
{
    foreach (string element in collection)
    {
        /* work with element */
    }
}

But if you need to access them by the index or know how many of them are in the collection, use IReadOnlyList:

public void SomeMethod(IReadOnlyList<string> collection)
{
    int count = collection.Count;
            
    /* use count */
 
    string element = collection[10];
}

So, be as liberal with the input collection type as you can, but not more. If you can’t make it work with IEnumerable, use IReadOnlyList.

Similarly, if you can return the more specific collection type from a method, do that. Use IReadOnlyList when possible. Fall back to IEnumerable when not.

Note that for private methods, it’s fine to use concrete collection types, such as List or Dictionary. You need to adhere to OCP only when the method is part of a public API.

IEnumerable vs IReadonlyCollection vs ReadonlyCollection for exposing a list member

IEnumerable vs ICollection vs IList

IReadOnlyCollection and IReadOnlyList

Just a quick note on the two above. IReadOnlyCollection is one of my favourite interfaces when combined with Repositories. You shouldn’t really be adding items directly to the collection you return from your repository (it may lead to unexpected side effects), so returning a read only version of your collection ensures this is not possible.

Performance Iteration

Performance between Iterating through IEnumerable and List

When you call ToList() on your IEnumerable, you are running a full iteration of your collection and loading all of the elements into memory with that iteration. This is worth doing if you expect to be iterating through the same collection multiple times. If you expect to iterate through the collection only once, then ToList() is a false economy: all it does is to create an in-memory collection that will later have to be garbage collected.

LINQ equivalent of foreach for IEnumerable

There is no ForEach extension for IEnumerable; only for List<T>. So you could do

items.ToList().ForEach(i => i.DoStuff());

Alternatively, write your own ForEach extension method:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}  

Be careful with ToList(), because ToList() creates a copy of the sequence, which could cause performance and memory issues. – decasteljau Aug 14 '09 at 12:37

IReadOnlyCollection instead of IEnumerable | Code {Sections}

But for the client developer IEnumerable<T> may signal something totally different as well: that the service doesn’t actually return the data they want but only a promise to be able to get the data eventually when trying to browse the “collection”. This would automatically raise awareness that it could turn into a performance issue as looping the collection multiple times would actually invoke multiple yield return calls internally within your service implementation. So the client developers will usually do a .ToArray() themselves to cache results and ensure best performance of their apps.

In the latest .NET Framework versions, however, you could use a better, intermediary, interface instead, IReadOnlyCollection<T>:

IReadOnlyCollection<T> Get();

That would clearly signal to the client developer that:

  • The data in the collection is already prepared by your service, and no cache is necessary to browse the collection multiple times;
  • Collection should be treated as immutable, i.e. the client code should only read it, and not update it; you can also use ReadOnlyCollection<T> class internally in the service implementation to host the items if you want to avoid casting of the returned object to a mutable collection on the client side;
  • There would be no issue if the data would be accessed later, such as after a connection is closed and the original promise of IEnumerable<T> would otherwise be compromised. 🙂

IEnumerable Vs IReadOnlyList

IEnumerable vs IReadOnlyList · Enterprise Craftsmanship

c# - IEnumerable vs IReadonlyCollection vs ReadonlyCollection for exposing a list member - Stack Overflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment