Use explicit Lambdas with LINQ

Here's an interesting bug... What's wrong with this code?

In principle, nothing. Your IDE might even encourage you to write this instead of the longer (but also more expressive):

Let me give you a couple of hints... First, the second version, the explicit one, works perfectly well, while the first one behaves very oddly in some contexts. Second, here's the signature for the Clone method:

Here's the key: LINQ's select method can take basically two signatures for its argument function. The first one is a simple mapping that takes a single parameter. The second takes the source item as its first argument, but has a second argument that is the index of the current element being processed in the source enumeration.

Now surely you can see how this causes a subtle bug in the first version of our code. Seeing that our method has an overload that takes two argument, the second being an integer, the compiler thinks our function needs the index as its second argument. Essentially, the compiler interprets our code as this:

As the code runs, our Clone method will get called with 0, 1, 2, 3, etc. as its max depth parameter, resulting, presumably, in very shallow, then deeper and deeper clones being made. Very strange behavior that will be extremely difficult to track down...

For those reasons, here's my recommendation: just be explicit, use the second version. Never pass the raw method as the argument to Select (and other LINQ methods), explicitly write a Lambda instead.

1 Comment

Comments have been disabled for this content.