Today, we’re taking a deeper look at
foreach loop in C#. What does a collection need to be able to use it in a
foreach loop? Does it have to implement
IEnumerable interface? These questions are often asked during interviews, so it’s worth knowing the answers ?
We will go through a step-by-step example in building our own custom collection to see how all that works. Let’s dive in! ?
Throughout this article, I’m working with a Unit Tests project using .NET 5, C# 9.0 and NUnit. It makes it easier to play with the code on your own. We can create our custom collection and at the same time try it out in a
foreach loop in a test method. I recommend this approach for testing out various programming concepts for yourself ?
Table of Contents
Custom collection implementing IEnumerable<T>
First, we want to implement our own, custom collection in C#. The most obvious solution is to implement
IEnumerable<T> interface. Our IDE will require our class to implement
IEnumerator GetEnumerator() and
IEnumerator IEnumerable.GetEnumerator() methods, so let’s do that:
Of course, this is just an example to satisfy the
foreach loop, so we won’t care about the actual implementation of these methods ?
Custom collection implemented in such a way can be used in
Does foreach require IEnumerable?
Let’s try to get rid of implementing
IEnumerable interface. As soon as we do it, our IDE complains:
Let’s try to remove
IEnumerable.GetEnumerator() method completely, so our custom collection looks as follows:
Now guess what – we can still use
MyCollection within the
So you already know that, when asked during an interview whether
foreach needs a collection to implement
IEnumerable, the answer is no ?
Currently, our collection has a single
GetEnumerator() method returning
IEnumerator<MyObject>. We already know that this method is needed in a collection to be able to use it within a
However, let’s work on what this method returns. We’ll implement our custom
IEnumerator. Again – the most obvious solution is to create a class implementing
That’s the implementation proposed by the IDE (Rider). We can now change our collection to use this custom enumerator. See that it can still be used within
So far, so good. But why all these methods in
Does foreach need an enumerator implementing IEnumerator?
If we remove inheritance from
MyObjectEnumerator, the IDE only complains about
IEnumerator.Current property, so let’s get rid of it. Our custom enumerator now looks as follows:
Yeah, you guessed it again – we can still use our collection in a
foreach loop ?
However… Does our custom enumerator really needs all of these stuff:
MyObject Current ? Let’s remove all of them and see what our IDE tells us:
That’s the error from IDE when trying to iterate through our custom collection in
Type ‘ForeachFun.MyCollection’ cannot be used in ‘foreach’ statement because it neither implements ‘IEnumerable’ or ‘IEnumerable’, nor has suitable ‘GetEnumerator’ method which return type has ‘Current’ property and ‘MoveNext’ method
This error actually tells us everything. This is the ultimate answer to the legendary C# interview question: “What does a collection need to be able to use it in
foreach loop?”. In other words: “Is it necessary for a collection to implement
IEnumerable to use it in a
The answer is: a collection needs to have a
GetEnumerator() method returning an object of type having
Current property and
bool MoveNext() method. No interfaces are required anywhere here ?
The compiler uses duck typing to find these two necessary ingredients of the type returned from
GetEnumerator(). It means that is looks for these properties by text. Later, depending on the type of
Current property, a single element inside the
foreach is typed accordingly. Only if this duck searching fails, the compiler checks whether the collection implements the interfaces.
In the end, this is our simplest and fully legit code (except the actual implementations of the methods, which is out of scope of this article):
I hope you got to know something new about
foreach loop from this article. This may not sound like a knowledge you’d need on a daily basis, but it’s worth knowing how stuff works under the hood ? Plus, you can always score a point during your next interview ?!