为什么IQueryable实现IEnumerable?

时间:2015-03-18 15:10:56

标签: c# linq ienumerable iqueryable

我理解为什么IQueryableIEnumerable exist,但我不清楚IQueryableIEnumerable获得的好处。

我遇到的一个缺点:

  • 任何创建自己的IEnumerable扩展程序的人都可能会轻易将无辜的IQueryable查询转换为效率低下的IEnumerable调用。例如,使用MoreLinq:

     Users.DistinctBy(u => u.Address).Where(u => u.Age >= 18)
    

(这将使用IEnumerable.Where而不是IQueryable.Where,除非我错过了IQueryable以上的实施方式)

IQueryable的工作方式,内部Expression被链接语句改变,似乎与链接函数通常需要工作的方式完全不同。

我怀疑这个接口继承有一些强大的优势,我可能没有充分利用它。与IQueryable实施IEnumerable相比,有什么好处,例如,有一个执行查询的显式转换?

1 个答案:

答案 0 :(得分:3)

(我认为从IQueryable继承IEnumerable是愚蠢的)...但是!

它只是起作用

这是.NET中的leitmotif集合。如果要在Contains集合上执行List<>(执行O(n)操作),则没有安全网。如果您多次重新执行相同的查询,则没有安全网,因为您不知道IQueryableIEnumerable之间的差异(请注意,即使IEnumerable也没有&#39} ; t保证结果的缓存:-))。

由于这种继承,接受IEnumerable / IEnumerable<T>的所有方法都接受IQueryable / IQueryable<T> / IOrderedQueryable<T>

它只是起作用

熟悉Variant数据类型的VB程序员团队...... .NET程序员团队会对慢查询感到满意: - )

与往常一样,这里有优雅的空间,并且有足够的空间进行草率编程。任何人都有空间: - )

我要补充一点,您提供的示例来自外部库,其说明为LINQ to Objects is missing a few desirable features. (并注意DistinctBy可以&#34;模拟&#34; GroupBy + Select(First()),因此可以构建IQueryable兼容的)。所以你使用像螺丝一样的锤子,你抱怨它不是正确的仪器: - )

Microsoft提供的不会生成集合的扩展方法通常为IQueryable - 安全(ExpressionFunc除外)

出于好奇,MSDN的正式理由是:

  

IQueryable接口继承IEnumerable接口,因此如果它表示查询,则可以枚举该查询的结果。枚举导致与IQueryable对象关联的表达式树被执行。

And

  

该接口继承IEnumerable&lt; T&gt;接口,以便如果它表示查询,则可以枚举该查询的结果。枚举强制与IQueryable&lt; T&gt;相关联的表达式树。要执行的对象。当调用Execute&lt; TResult&gt;(Expression)方法时,将执行不返回可枚举结果的查询。

可悲的是(至少对我来说),这不是一个足够好的理由,因为他们可以拥有

  • 只需让AsEnumerable()以明确的方式完成工作

  • 在方法IQueryable中加入GetEnumerator()(和相关的)接口,因为foreach使用鸭子打字,它会很高兴。

例如:

public interface IMyEnumerabe<T>
{
    IEnumerator<T> GetEnumerator();
}

IMyEnumerabe<int> myenumerable = null;

foreach (int el in myenumerable)
{
    // Compiles (and in this cases crashes with a NullReferenceException :-) )
}