We are going to look into details of different kinds of iterator supported by C# and find out subtle differences between them.
Introduction
There are following two different types of iterator supported
by C#.
1) External
iterator
2) Internal
iterator
Whatever differences exist between them have been marked in Bold letter so, look at them very carefully.
1) External iterator:
A statement in which we need to specify each single step to complete the
task. Consider below code snippet
List<string> cities = new List<string> { "Vadodara", "Surat", "Anand" };
for (int i = 0; i < cities.Count; i++)
{
Console.WriteLine(cities[i]);
}
This is very simple code. we already have been using
this kind of codebase in our day to day application. We are just iterating over
elements (string type) of list collection. It might be others like dictionary,
array, hash table or custom collection. But it contains so many moving parts. Some developers might
argue that this very old way to iterate over collection. They could be writing
same codebase in the following ways
foreach (var city in cities)
{
Console.WriteLine(city);
}
Despite the above and prior one code produces the same
output, but above one is much better than the prior one because former one
contains more moving parts. But even more important thing is that there are
semantical differences between
for
and
foreach construct, for which we
must be very thoughtful. That difference is
mutability.
List<string> cities = new List<string> { "Vadodara", "Surat", "Anand" };
for (int i = 0; i < cities.Count; i++)
{
Console.WriteLine(cities[i]);
i = 44;
}
Above codebase only print first value from the
collection because variable i is mutable (reinitialize its value) and it
affects the state of iterator. This one is the very big design flow in the loop construct itself because i should not be mutable if it was
iterating the index. On the contrast look at the below code
foreach (var city in cities)
{
Console.WriteLine(city);
city = "Nadiad";
}
Here variable(
city)
is
immutable, means
we cannot change value of city
variable. If we try, then compiler become unhappy and gives above compile-time
error message.
In above both (for
and foreach) code, we need to specify
what to do and how to do part such kind of programming style is known as imperative style of programming.
2)Internal iterator:
An expression is
more concise and expressive. Let’s look at the below example
List<string> cities = new List<string> { "Vadodara", "Surat", "Anand" };
cities.ForEach(city => Console.Write(city));
Here foreach
function is a higher-order function,
means if a function takes one or more functions as arguments it is called high-order function (functional
form/ functor). In the above code snippet ForEach function contains anonymous
function(city=>Console.Write(city). It produces the same result as prior external iterator
(for and foreach). But this code snippet is declarative in nature. Declarative
means we only need to specify what
we want to do with each element, rather than how it does.
In contrast to the external iterator where we must specify
every minute details like starting value, exit condition and so on, here we are giving up
control of certain part of our code to underlying library (Base class library).
So, we better focus on other important part of our business logic rather than
the thing we don’t need to care about. It also relives us from many duties as
programmer.
One more important point about internal iterator is it
supports polymorphism (Dynamic binding).
The dot(.) before ForEach function is a polymorphic
means it says just go ahead and call me and I will tell you what I do but does
not reveal its how I do it. At runtime, it will work out how to do it based on
the context of Object it is working with. So, we get little bit flexibility
through internal iterator in our code compare to external iterator. Both
for/foreach construct are example of static
binding. So, such kind of programming style is called declarative style of programming.
Conclusion
To summarize, whenever you need to do a lot of manual loops
through the data structure, wait for a minute and start thinking about the internal
iterator. Because C# language has the power but the biggest problem is our mindset.
As C# developer, our mind is wired with for/foreach loop construct since the
long-time only because we are familiar with it, not because it provides better
way of programming. We just need to re-tuning our mindset. Then our code will express
our ideas in nicer way. Only need to frame set of functions together like
List<string> cities = new List<string> { "Vadodara", "Surat", "Anand" };
var query = cities.Where(n => n.Contains("V"))
.OrderBy(n => n.Length)
.Select(n => n.ToUpper());