C# IEnumerable和IQueryable-两个世界中最好的

C# IEnumerable和IQueryable-两个世界中最好的,c#,ienumerable,iqueryable,C#,Ienumerable,Iqueryable,出于性能原因,我的许多服务现在都返回IQueryables,因此调用方可以在实现之前决定过滤哪些元素。出于设计原因(接口等),我更愿意返回IEnumerables,但这肯定会消除IQueryables的优点:完整结果集的物化加上非异步方法 我已经开始编写一些更喜欢IQueryable而不是IEnumerable的扩展方法,例如: public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TS

出于性能原因,我的许多服务现在都返回IQueryables,因此调用方可以在实现之前决定过滤哪些元素。出于设计原因(接口等),我更愿意返回IEnumerables,但这肯定会消除IQueryables的优点:完整结果集的物化加上非异步方法

我已经开始编写一些更喜欢IQueryable而不是IEnumerable的扩展方法,例如:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate)
    => source is IQueryable<TSource> ? Queryable.Where(source as IQueryable<TSource>, predicate) : Enumerable.Where(source, predicate.Compile());

public static Task<TSource[]> ToArrayAsync<TSource>(this IEnumerable<TSource> source)
    => (source as IQueryable<TSource>)?.ToArrayAsync() ?? Task.FromResult(source.ToArray());
公共静态IEnumerable Where(此IEnumerable源,表达式谓词)
=>源是否可用?Where(源为IQueryable,谓词):可枚举的.Where(源,谓词.Compile());
ArrayaSync的公共静态任务(此IEnumerable源)
=>(源为IQueryable)?.ToArrayAsync()??Task.FromResult(source.ToArray());
我不可能是唯一一个想到这个的人。这些方法有什么改进吗?已经有好的收集/解决方案了吗?或者这是一个糟糕的设计?所以请告诉我原因


谢谢大家!

就我个人而言,这会让我变得谨慎;序列和查询是相似的,但差异很大,所以我非常想确定它是如何处理的。与在capture-context上使用直接编译器生成的方法相比,生成表达式树并对其进行编译还涉及到一些非常重要的开销。如果表达式树将用作查询组合和转换的一部分,那么它的开销是合理的,但在序列情况下不需要

也许更明显的方法是对序列使用
AsQueryable()
来模拟真正的查询

但是:我想你所拥有的应该有用。作为一个次要的语法注释,在最近的C#版本中,您可以将键入的值作为
is
的一部分来捕获,以避免重复转换:

公共静态IEnumerable Where(此IEnumerable源,表达式谓词)
=>源是可读取的q?可查询的.Where(q,谓词):可枚举的.Where(source,predicate.Compile());
Compile()
上的布尔标志进行实验也可能很有趣-使用解释模式可以降低执行速度,但可以避免生成IL。这对小数据集可能是积极的影响,而对大数据集可能是消极的影响


附带说明:可查询源有多个异步实现;EF核心有一个,IX(无功的一部分)有另一个。它们彼此不兼容,使用不同的方法,但两者都可以根据您的场景工作。

如果要将其用作
IQueryable
,为什么要返回
IEnumerable
?这只会让事情变得不那么明显。谢谢你非常详细的回答!还有额外的密码糖!我不知道-我喜欢!在我的“框架”中,有几个服务需要通过接口返回IEnumerable,但只能返回IQueryable。如果确实返回IQueryable,我不希望所有调用方都检查实际的返回类型,而是选择性能最好的返回类型。所以对于我的内部用例,你会说我的方法是可以的?除了额外的代码sugar:)@tris它会工作的;其他一切都是主观的;可能会有一些开销,但这是否重要取决于上下文——因此:我们不能真正注释——但是:回到我的AsQueryable注释:那里的代码已经检查了“is IQueryable-t”,所以老实说:我只使用AsQueryable();引文:(上面还有几行是通用版本)是的,谢谢-可能是最好的解决方案,实际上正是我想要的: