public static IEnumerable<T> Pipe<T>(this IEnumerable<T> source, Action<T> action)
{
return _(); IEnumerable <T> _()
{
foreach (var element in source)
{
action(element);
yield return element;
}
}
}
I've found this code in MoreLinq repo and can't understand this line:
return _(); IEnumerable <T> _()
This code uses a relatively new feature of C#, called local function. The only unusual thing about this function is its name: developers used a single underscore for it. Hence, the name of the function is _
, so the invocation looks like this: _()
Now that you know that return
statement returns the result of invoking a local function named _
, the rest of the syntax falls into place:
// This is a local function
IEnumerable <T> _() {
...
}
(OP's comment on the question) Can't we just do
foreach
withyield return
?
The method that you copied included two additional lines, which are key to understanding the difference:
public static IEnumerable<T> Pipe<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (action == null) throw new ArgumentNullException(nameof(action));
return _(); IEnumerable <T> _()
{
foreach (var element in source)
{
action(element);
yield return element;
}
}
}
If you put foreach
with yield return
directly into the body of Pipe<T>
method, argument checking would be deferred until you start iterating your IEnumerable<T>
result. With local function in place you would do the check as soon as Pipe<T>
is called, even in situations when the caller never iterates the result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With