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