Yesterday I was working on some fairly complex code involving some LINQ to SQL, lots of generics (with some reflection generously sprinkled on top) and some extension methods to complete the cake.

Most was working as expected, until I ran into a little snag. I had one line of code looking a bit like this:

DoSomething<MyType>(someCollection);

When I ran my NUnit tests, it appeared as if DoSomething() had never been executed. I knew that someCollection had some items in it, so I was pretty surprised. I fired up a debugger, put a breakpoint in the first line in of DoSomething and execute the code. No dice, the breakpoint wasn't even hit.

So I went one step further and put a breakpoint just at the call to DoSomething. The breakpoint got hit, pressed F11 (step into) and.... it went right to the next line without stepping into the method. What was up with that?

After scratching my head a lot, I realized it had been me being clever that caused the problem. See, DoSomething was basically a map of sorts, defined somewhat like this:

IEnumerable<T> DoSomething<T>(IEnumerable list) {
   foreach ( var obj in list )
      yield return obj.Map<T>();
}

Can you spot the problem?

I had created the method so that I could reuse the transformed object stream after the mapping, just in case I needed it. However, on this particular use I was making of the method I was disregarding the return and was simply interested in getting the internal function called for each item in the collection.

This turned out to be a really bad idea, because the way the C# compiler generates the code for this is pretty smart: It's completely pipelined/streamed, such that you need to consume the returned IEnumerable object. If you don't, then the collection provider never gets iterated on, and thus, nothing happened.

In hindsight, this should've been pretty obvious, and it's a very natural behavior, if you think about it. I should've been able to pick it up sooner, but I admit the debugger behavior surprised me a bit.

Technorati tags: , , ,


Tomas Restrepo

Software developer located in Colombia.