我正在寻找问题的答案 Get next N elements from enumerable没有找到任何令人满意的并酿造了我自己的。我想到的是
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);
}
}
不过,我真正想要的是让 action 的默认值为 t=>t
,但我不知道如何使它成为默认参数。签名IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action = t=>t)
给出语法错误。
我的问题是,我该怎么做?
我想这与 Specifying a lambda function as default argument 相同但对于 C# 而不是 C++
作为旁注,我知道它在语法上没有任何区别,但如果我切换 T
会更容易阅读吗?和 R
?
最佳答案
默认值必须是常量,委托(delegate)的唯一常量值是 null
引用。
我建议您改用重载。注意 t => t
无论如何都无效,除非您知道有一个来自 IEnumerable<R>
的转换至 T
,我在任何地方都看不到。
除了 lambda 表达式有效性问题,您可以使用空合并运算符:
IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n,
Func<IEnumerable<R>, T> action = null)
{
action = action ?? (t => t);
...
}
...但那有点滥用它,您将无法判断 null
是否是实际上 来自认为他们正在传递非空值的调用者,并且希望您提出 ArgumentNullException
.
编辑:此外,请注意您的方法存在根本性问题 - 迭代 block 将多次评估原始序列(每个 block 一次)以跳过正确的数量。最好编写一个方法,在返回之前急切读取每个 block 。我们在 MoreLINQ 中有类似的方法, 称为 Batch
.注意 Batch
正好有这里提到的过载 - 在这种情况下,t => t
有效,因为重载的类型参数较少,所以我们知道身份转换没问题。
关于c# - lambda 作为默认参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11140348/