Skip Navigation LinksHome > View Post

Using .Select() instead of foreach

As astute colleague noticed something funny in my recent post. Specifically, this piece of code:

postsWithCount.AsEnumerable().Select(pd => Rebuild(pd));

private void Rebuild(PostData postData)
{
    Post post = postData.Post;
    post.User = postData.User;
    post.Comments.Attach(postData.Comments);
}

What on earth am I doing here? Maybe it will help if I write the same code in a different way:

foreach (var postData in postsWithCount)
{
    Rebuild(postData);
}

private void Rebuild(PostData postData)
{
    Post post = postData.Post;
    post.User = postData.User;
    post.Comments.Attach(postData.Comments);
}

Yup, I'm quite naughtily using Select as a ForEach. I've been experimenting with this for a while now and the outcome is clear - it makes your code confusing.

Sadly, there is a ForEach<> method on System.Array but no extension method for IEnumerable<> :(

UPDATE: There are two humdingers in this post that people correctly noted in comments and e-mail to me:

  • The Select() extension method is delayed and, in the example above would likely never get executed. This is a good lesson in testing code before you post it to your blog. The example was cut & paste together from subtly different code where this wouldn't have happened and that led to these mistakes. Oops.
  • This example wouldn't even compile - the Select() extension expression must return something but my Rebuild is void so this would have resulted in a compiler error. Oops again.

These are embarassing mistakes to make and I was tempted to just delete the post, but that would seem dishonest somehow, so I'll leave it here with this note.

The lesson is clear though: DON'T USE Select() INSTEAD OF foreach :)

 
Josh Post By Josh Twist
6:10 PM
12 Feb 2009

» Next Post: Creating reusable Entity Framework queries thanks to deferred execution
« Previous Post: Sorting associations in the Entity Framework

Comments are closed for this post.

Posted by Erik @ 12 Feb 2009 11:38 PM
"Sadly, there is a ForEach<> method on System.Array but no extension method for IEnumerable<> :("

-- So make one and use it. Everybody's doing it... >:D

Posted by josh @ 13 Feb 2009 5:19 AM
Lol! Aren't they just. I think Umbrella has this too.

Posted by Mike Strobel @ 13 Feb 2009 1:16 PM
Interesting thing about the example in your post is that the Rebuild method will never actually get executed because the Select operation is deferred. I'm sure in your original code you had another statement to force immediate execution, like so:

postsWithCount.AsEnumerable().Select(pd => Rebuild(pd)).Count();

Posted by Grant BlahaErath @ 15 Feb 2009 3:56 PM
Maybe you need to use a foreach to force execution. :-)

Delayed execution could have it benefits though. I wouldn't put this technique to bed yet.

© 2005 - 2014 Josh Twist - All Rights Reserved.