When using a very simple expression as key to create an ILookup with Enumerable.ToLookup<TSource, TKey> Method (IEnumerable<TSource>, Func<TSource, TKey>) I can use a lambda expression:
var lk = myItems.ToLookup((x) => x.Name);
or a local function:
var lk = myItems.ToLookup(ByName);
string ByName(MyClass x)
{
return x.Name;
}
I'm curious if there is a difference in this simple case.
In his answer to Local function vs Lambda C# 7.0 SO user svick gives a good argument why –in general– local functions are preferable to lambdas.
An important point is the difference in performance:
When creating a lambda, a delegate has to be created, which is an unnecessary allocation in this case. Local functions are really just functions, no delegates are necessary.
But since we pass it to ToLookup() a delegate is created anyway. Is there still a difference in performance?
I can imagine that the compiler has to create a fresh delegate lambda for each invocation of myItems.ToLookup, whereas there only needs to be a single delegate instance for the local method; is this true?
A second point of difference in performance in svick's answer is the capturing of variables and the creation of closures:
Also, local functions are more efficient with capturing local variables: lambdas usually capture variables into a class, while local functions can use a struct (passed using ref), which again avoids an allocation.
However, since the expression does not use variables from the outer scope, there does not have to be a closure as stated by Reed Copsey and expanded by Eric Lippert in answer to Are Lambda expressions in C# closures?:
A lambda may be implemented using a closure, but it is not itself necessarily a closure. — Reed Copsey
[...]
a function that can be treated as an object is just a delegate. What makes a lambda a closure is that it captures its outer variables. — Eric Lippert
This is somewhat contradicted Eric Lippert himself is his answer to Assigning local functions to delegates Eric Lippert explains a local function as a named lambda:
A local function is basically just a lambda with an associated name.
But this is at a level of lesser technical detail and for delegates of lambda's/local functions that do capture outer scope variables.
This simple expression is not recursive, not generic, and not an iterator. And which looks better is a matter of opinion.
So, are there any differences in performance (or otherwise) between simple not capturing, non recursive, non generic, and non iterator lambda expressions and local functions?