10

我经常发现自己想在 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 中实现?

4

3 回答 3

17

从技术上讲,您的 Head 将是.First()而您的 Tail 将是.Skip(1)。但也许你能找到更好的解决方案?喜欢在 IEnumerable 上使用.Aggregate()吗?

于 2013-10-25T08:59:51.553 回答
8

给定的接口IEnumerable<T>,性能不能总是得到保证。

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

IEnumerable<T>没有任何此类约束,因此不能假设这将是有效的。

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

例如,如果您使用实体框架执行此操作,您将发送以下(元)调用到 SQL 服务器,紧密循环。

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

这将是非常低效的。

编辑:

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

于 2013-10-25T09:13:08.410 回答
1

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

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

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

于 2013-10-25T09:08:24.133 回答