为什么Linq没有头和尾?

时间:2013-10-25 08:56:36

标签: c# linq head tail

我经常发现自己想在IEnumerables上使用Head和Tail方法,这些方法在Linq中不存在。虽然我可以很容易地写自己的,但我想知道他们是否被故意排除在外。例如,

var finalCondition = new Sql("WHERE @0 = @1", conditions.Head().Key, conditions.Head().Value);
foreach (var condition in conditions.Tail())
{
  finalCondition.Append("AND @0 = @1", condition.Key, condition.Value);
}

那么,与Linq有关的最佳做法是什么?事实上,我一直在寻找这个标志,我没有做推荐的事情吗?如果没有,那么为什么这个常见的功能范例没有在Linq中实现?

3 个答案:

答案 0 :(得分:16)

从技术上讲,你的头部将是.First()而你的尾部将是.Skip(1)。但也许你可以找到更好的解决方案?就像在IEnumerable上使用.Aggregate()一样?

答案 1 :(得分:8)

鉴于IEnumerable<T>的界面,不能始终确保表现。

您注意到大多数函数式编程语言都实现了tail和head。但是应该注意的是,这些语言在内存构造中起作用。

IEnumerable<T>没有任何此类限制,因此不能假设这样做有效。

例如,一个常见的功能模式是递归地处理集合的头部,然后递归到调用的尾部......

如果您使用Entity Framework执行此操作,则会将以下(meta)调用发送到SQL服务器,紧密循环。

Select * from
(
    Select * from
    (
         Select * from
         (...)
         Skip 1
    )
    Skip 1
);

这将是非常低效的。

编辑:

来考虑一下。另一个原因是,C#/ VB.Net不支持尾递归,因此,这种模式很容易导致StackOverflow

答案 2 :(得分:1)

因为“Head&amp; Tail”概念用于pattern matching和递归调用的函数式编程。 由于C#不支持模式匹配,因此不需要实现head()和tail()方法。

let rec sum = function
  | [] -> 0
  | h::t -> h + sum t

至于你的情况 - 你应该使用Aggregate方法。