Lambda as default argument

I was looking for the answer to the question Get the following N elements from the enumerated one , I did not find any satisfying and welded by me. What I came up with was

IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action){ IEnumerable<R> head; IEnumerable<R> tail = src; while (tail.Any()) { head = tail.Take(n); tail = tail.Skip(n); yield return action(head); } } 

I would really like the action to have a default value of t=>t , but I cannot figure out how to make this argument by default. The signature IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action = t=>t) gives a syntax error.

My question is: how do I do this?

I believe this is identical. Specifying a lambda function as the default argument , but for C # instead of C ++

As a note, I know that it makes no syntactic difference, but would it be easier to read if I switched T and R ?

+4
source share
2 answers

The default values ​​must be constants, and the only constant value for the delegate is a null reference.

I suggest you use overload instead. Note that t => t not valid in any case, unless you know that there is a conversion from IEnumerable<R> to T that I cannot see anywhere.

In addition to the validity problem of the lambda expression, you can use the null coalescing operator:

 IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action = null) { action = action ?? (t => t); ... } 

... but it would be like abusing it, and you won’t be able to determine if null was really from the caller who thought they were passing a non-zero value, and would rather you raise an ArgumentNullException .

EDIT: Also, note that your method is fundamentally problematic - repeating fragments will evaluate the original sequence several times (once per piece) to skip the desired amount. It would probably be better to write a method that every piece would read with impatience before returning. We have a similar method in MoreLINQ called Batch . Note that Batch has the overload specified here, and in this case t => t works, because the overload has fewer type parameters, so we know that the identity conversion is fine.

+10
source

Same for C #: create overload.

 IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n){ return Chunk<T, R>(src, n, t => t); } 
+2
source

All Articles