Far*_*yev 13 .net c# linq ienumerable iqueryable
假设我需要一个扩展方法,它只选择不同来源的必需属性.源可以是数据库或内存中的集合.所以我定义了这样的扩展方法:
public IQueryable<TResult> SelectDynamic<TResult>(
this IQueryable<T> source,
...)
Run Code Online (Sandbox Code Playgroud)
这适用于IQueryables.但是,我也必须为IEnumerables 调用此函数.
在这种情况下,我可以在以下帮助下调用它.AsQueryable():
myEnumerable.AsQueryable()
.SelectDynamic(...)
.ToList();
Run Code Online (Sandbox Code Playgroud)
两者都很好.我有这样的问题,如果两者都工作正常,在哪些情况下我必须为同一目的创建两个不同的扩展方法,一个与之合作IEnumerable,另一个与IQueryable?
我的方法必须在以下情况下向数据库发送查询Queryable.
例如,以下是命名空间.Select 内的扩展方法的来源System.Linq:
我再次重复我的主要问题:
我的方法必须发送查询到数据库Queryable,但不是在使用时IEnumerable.而就目前而言,我正在使用AsQueryable()枚举器.因为,我不想为此编写相同的代码Enumerable.可以有一些副作用吗?
如果您的代码仅在其处理的对象加载到内存中时才能正常工作,只需提供IEnumerable变量并让您的调用者决定何时将其IQueryable转换为内存中IEnumerable.
通常,IQueryable除非您正在编写新的数据库提供程序,否则不会实现新的变体.
myEnumerable.AsQueryable()返回一个自定义对象:(new EnumerableQuery<TElement>(myEnumerable);源代码)
这个EnumerableQuery类实现IEnumerable<T>并IQueryable<T>
当使用EnumerableQuery的结果.AsQueryable()作为 时IEnumerable,接口方法的实现IEnumerable<T>.GetIterator()只是返回原始源迭代器,因此没有任何变化并且开销最小。
当使用 的结果.AsQueryable()作为 时IQueriable,接口属性的实现IQueriable.Expression只是返回Expression.Constant(this),准备好稍后在使用整个表达式树时作为 IEnumerable 进行计算。
EnumerableQuery(据我所知,当 EnumerableQuery 直接从 IEnumerable 构造时,所有其他方法和代码路径并不真正相关)
如果我理解正确的话,您已经selectDynamic<TResult>()以在方法内部构造表达式树的方式实现了您的方法,该表达式树在编译时会产生所需的结果。
据我了解源代码,当您调用 eg 时myEnumerable.AsEnumerable().selectDynamic().ToList(),您构建的表达式树将在 myEnumerable 上编译并执行,并且总开销应该相当小,因为所有这些工作每个查询只完成一次,而不是每个元素一次。
所以我认为像这样实现 IEnumerable Extension 方法没有任何问题:
public IEnumerable<TResult> SelectDynamic<TResult>(
this IEnumerable<T> source,...)
return source.AsQueryable().SelectDynamic();
}
Run Code Online (Sandbox Code Playgroud)
有一些轻微的开销,因为每次调用此方法时都会编译一次查询,并且我不确定 JITer 是否足够智能来缓存此编译。但我认为在大多数情况下这不会引人注目,除非您每秒执行此查询一千次。
以这种方式实现 IEnumerable 扩展方法时,除了轻微的性能问题外,不应该有其他副作用。