【问题标题】:lambda as default argumentlambda 作为默认参数
【发布时间】:2012-06-21 22:37:44
【问题描述】:

我一直在寻找问题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);
  }
}

我真正想要的是让动作默认为t=&gt;t,但我不知道如何将其设为默认参数。签名IEnumerable&lt;T&gt; Chunk&lt;T, R&gt;(IEnumerable&lt;R&gt; src, int n, Func&lt;IEnumerable&lt;R&gt;, T&gt; action = t=&gt;t) 给出了语法错误。

我的问题是,我该怎么做?

我想这与 Specifying a lambda function as default argument 相同,但用于 C# 而不是 C++

顺便说一句,我知道它在语法上没有任何区别,但是如果我切换T 和R 会更容易阅读吗?

【问题讨论】:

  • 旁注:是的,我至少会切换它们,并可能将它们重命名为 TSource 和 TResult。 (我认为这样会匹配默认的 LINQ 方法。)

标签: c#


【解决方案1】:

默认值必须是常量,并且委托的唯一常量值是null 引用。

我建议您改用重载。请注意,t =&gt; t 无论如何都不会有效,除非您知道从 IEnumerable&lt;R&gt; 到 T 的转换,我在任何地方都看不到。

除了 lambda 表达式有效性问题,您可以使用空值合并运算符:

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

... 但这有点滥用它,您将无法判断 null 是否实际上来自认为他们传递非空值的调用者价值,并希望您提出ArgumentNullException。

编辑:此外,请注意,您的方法从根本上是有问题的 - 迭代块将多次评估原始序列(每个块一次)以跳过正确的数量。最好编写一个方法,在返回之前急切读取每个块。我们在MoreLINQ 中有一个类似的方法,称为Batch。请注意,Batch 正是这里提到的重载 - 在这种情况下,t =&gt; t 有效,因为重载的类型参数较少,所以我们知道身份转换是可以的。

【讨论】:

  • 在 linqpad (yield return action(head) -> yield return head) 中使用 pastebin.com/T3RDxg7x 和 t => t 按预期工作。我在这里错过了什么?
  • @Martijn:在您的情况下,调用代码知道转换是好的,因为它知道类型参数(IEnumerable&lt;int&gt; 和int)。泛型方法不知道这一点。
  • 评论编辑:我希望result = Skip(n) 是 O(n) 而不是 O(结果大小),给我“只”两次迭代集合(加上任何操作) - 都假设它是一个可以多次迭代的集合。像 MoreLINQ 那样使用存储桶可能是更明智的想法。
  • 旁注:我的第一个 Skeet 答案。直到现在我才觉得自己是一个真正的 StackOverflow 成员。
  • @Martijn: 你返回src.Take(10),然后是src.Skip(10).Take(10),然后是src.Skip(10).Skip(10).Take(10) 等等。每个Skip 的结果是一个新的惰性评估序列- 每次你迭代它(包括如果你从它构建另一个序列并迭代它)它将从头开始。懒惰的评估可能会令人痛苦:(
【解决方案2】:

对于 C# 也是如此:创建重载。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多