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
18:10
12 Feb 2009

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

Comments:

Posted by Erik @ 12 Feb 2009 23:38
"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 05:19
Lol! Aren't they just. I think Umbrella has this too.

Posted by Mike Strobel @ 13 Feb 2009 13:16
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 15:56
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.

Posted by Alexander Kostikov @ 20 Feb 2009 04:39
I'm using my utils assembly with extensions:

public static IEnumerable<T> Action<T>( this IEnumerable<T> source, Action<T> action )
{
foreach( T element in source )
{
action( element );
}

return source;
}

Post a comment:

Name  

E-mail (never shared)

URL

Comments  

Captcha ImageRefresh Image
What's this?
Enter code above