73

What is IEnumerable in .NET? What is the explanation?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
qnatestu1
  • 739
  • 1
  • 5
  • 3
  • 31
    To be honest, the definition on MSDN is very scary for a beginner, when all you want to do is a foreach. – SWeko Jun 10 '10 at 13:36
  • 13
    Whilst I can understand why it was closed, I came to this from Google after MSDN wasn't that clear, and the answers have really helped me. If I could, I would vote for re open....This comes high up when Googling for "What is IEnumerable" and I am sure others have found it helpful. – Wil Apr 02 '11 at 18:00

5 Answers5

77

It's ... something... that you can loop over. That might be a List or an Array or (almost) anything else that supports a foreach loop. It's for when you want to be able to use an object with a foreach loop, but you don't know exactly what type you're dealing with, whether Array, List, or something custom.

So that's the first advantage there: if your methods accept an IEnumerable rather than an array or list they become more powerful because you can pass more different kinds of objects to them.

Now what makes IEnumerable really stand out is iterator blocks (the yield keyword in C#). Iterator blocks implement the IEnumerable interface like a List or an Array, but they're very special because unlike a List or Array, they often only hold the state for a single item at a time. So if you want to loop over the lines in a very large file, for example, you can write an iterator block to handle the file input. Then you'll never have more than one line of the file in memory at a time, and if you finish the loop earlier (perhaps it was a search and you found what you needed) you might not need to read the whole file. Or if you're reading the results from a large SQL query you can limit your memory use to a single record.

Another feature is that this evaluation is lazy, so if you're doing complicated work to evaluate the enumerable as you read from it, that work doesn't happen until it's asked for. This is extra beneficial, because often (say, for searches again) you'll find you might not need to do the work at all.

You can think of IEnumerable as if it were a just-in-time List.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 2
    The key of `IEnumarable` is that the backing collection is `not enumerated` until specifically expanded, be it a foreach or accessor via an indexer. Unfortunately IEnumarable seems to be blindly used as the lowest interface which now causes problems with asynchronous data manipulation (e.g. executing SQL on GarbageCollected contexts). I would say that `ICollection` is every thing you said apart from the "lazy evaluation" and we should be using that, especially if the data has already been enumerated once! – Piotr Kula May 30 '17 at 10:10
  • 1
    Best simple explanation in plain English, hats-off! – Jeb50 Apr 15 '18 at 22:42
  • I think IEnumerable is poorly named. Mathematically, and in computing, an enumerable is anything that maps to a countable set. So outside of .net an IObservable may be enumerable. In .NET IEnumerable is considered the dual opposite of IObservable in a pull vs push duality. The intention of IEnumerable seems to be what Java calls Iterable, which in my mind is a better name. – Sentinel Jun 06 '18 at 08:29
35

It's an interface implemented by Collection types in .NET that provide the Iterator pattern. There also the generic version which is IEnumerable<T>.

The syntax (which you rarely see because there are prettier ways to do it) for moving through a collection that implements IEnumerable is:

IEnumerator enumerator = collection.GetEnumerator();

while(enumerator.MoveNext())
{
    object obj = enumerator.Current;
    // work with the object
}

Which is functionaly equivalent to:

foreach(object obj in collection)
{
    // work with the object
}

If the collection supports indexers, you could also iterate over it with the classic for loop method but the Iterator pattern provides some nice extras like the ability to add synchronization for threading.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • Note, depending the syntax shown here is the C# 5 equivalent of a foreach. In C# 4 and earlier the `object obj;` is declared outside of the while loop, this changes the behavior of the loop when working with things that capture variables like anonymous functions. – Scott Chamberlain Dec 09 '16 at 18:16
  • tech-over-tech answer just brings up more confusion and frustration. – Jeb50 Apr 08 '18 at 16:58
13

First it is an interface. The definition according to MSDN is

Exposes the enumerator, which supports a simple iteration over a non-generic collection.

Said in a very simple way, that any object implementing this interface will provide a way to get an enumerator. An enumerator is used with the foreach as one example.

A List implements the IEnumerable interface.

    // This is a collection that eventually we will use an Enumertor to loop through
    // rather than a typical index number if we used a for loop.
    List<string> dinosaurs = new List<string>();

    dinosaurs.Add("Tyrannosaurus");
    dinosaurs.Add("Amargasaurus");
    dinosaurs.Add("Mamenchisaurus");
    dinosaurs.Add("Deinonychus");
    dinosaurs.Add("Compsognathus");

    Console.WriteLine();

    // HERE is where the Enumerator is gotten from the List<string> object
    foreach(string dinosaur in dinosaurs)
    {
        Console.WriteLine(dinosaur);
    }

    // You could do a 
    for(int i = 0; i < dinosaurs.Count; i++)
    {
        string dinosaur = dinosaurs[i];

        Console.WriteLine(dinosaur);
    }

The foreach looks cleaner.

David Basarab
  • 72,212
  • 42
  • 129
  • 156
7

The short answer is that it's anything you can use a foreach on.

SWeko
  • 30,434
  • 10
  • 71
  • 106
0
  • It is a base interface that enables us to loop or iterate over an Collection.

  • The most important note about IEnumerable is that when you go through an object or collection it just holds the state of a single item at a time.

  • It has a good performance when you are iterating through big objects or collections because it does not load the entire object to memory in order to make iteration. for instance, suppose you decided to read a large file line by line and doing something on that, therefore you can write your own ReaderEnumrable to read your file with high performance.

  • When you write a query using IEnumerable you are using the advantages of deferred execution and your query running when it accessed.

  • Each time you run you iterate through a collection, a different collection created. For example in the following code each time the listOfFiles accessed the ListOfAllFiles execute again.

    public static void Main()
    {
        var listOfFiles = ListOfAllFiles();
    
        var filesCount = listOfFiles.Count();
        var filesAny = listOfFiles.Any();
        var fileIterate = listOfFiles.Select(x => x.FullName);
    }
    
    private static IEnumerable<FileInfo> ListOfAllFiles()
    {
        foreach(var file in Directory.EnumerateFiles(Environment.CurrentDirectory))
        {
            yield return new FileInfo(file);
        }
    }