For loops have been our friend for so many years. I have fond memories of looping through huge lists of items imperatively bobbing and weaving to construct my final masterpiece!
1.for
(int
i = 0; i < items.Length; i++)
2.{
3. if
(items[i].SomeValue == "Value I'm Looking For!")
4. {
5. result.Add(items[i]);
6. }
7.}
Look at that beauty. I am looping through a list of items, filtering them on some value, and then BAM! I get a result list with the values in it. Magic I tell you, magic. And then foreach loops came along and I realized how ridiculously ugly it was. Just check this out:
1.foreach
(SomeDummyClass item in
items)
2.{
3. if
(item.SomeValue == "Value I'm Looking For!")
4. {
5. result.Add(item);
6. }
7.}
Mmmmm. Beauty, simplicity, less room for error. But I still have to do a lot of declaring and looping and things. Ugh. So then they gave me the magical yield statement, and when used with a method, I could do this:
01.private
static
IEnumerable<SomeDummyClass> GetItems(SomeDummyClass[] items)
02.{
03. foreach
(SomeDummyClass item in
items)
04. {
05. if
(item.SomeValue == "Value I'm Looking For!")
06. {
07. yield return
item;
08. }
09. }
10.}
Nice. Still a lot of looping, but now I don't have to declare that stupid result list. And, if the result is never used, nothing even runs! Lazy evaluation rocks your face people! This still just feels gross though. Why am I holding the compilers hand so much? I just need to say "hello computer, give me crap in this list where SomeValue = some crap I'm looking for". Lo and behold Anders Hejlsberg and his team came down from on high and delivered Linq to us. Now I say:
1.var result = items.Where(i => i.SomeValue == "Value I'm Looking For!");
And the compiler figures it all out for me. Better yet I still get lazy evaluation and I get my list filtered. Best of both worlds! And since I am not telling the compiler exactly what to do, then in the future (with .NET 4.0) when my list grows really really large, all I have to do is say:
1.var result = items.AsParallel().Where(i => i.SomeValue == "Value I'm Looking For!");
And suddenly my list is being filtered by all of the processors on the box! This is possible because at each iteration we began to tell the computer less and less how to perform the individual operations needed in order to get our result, and instead we are now more closely telling the computer the action to take, not the specifics of how to perform the action. This lets the computer best decide how to execute our action, and in the case of Parallel Linq, we are now able to tell the framework that we want our task executed in parallel. (In case you are wondering, there are a few reasons why it can't just run it as parallel by default)
As you can see, we really are moving more and more down the road of declarative development. Over time we will see more "what" and less "how" in our day to day programming adventures. And that, my friends, is life after loops.