在哪种情况下,我需要为IEnumerable和IQueryable创建两种不同的扩展方法? [英] In which cases do I need to create two different extension methods for IEnumerable and IQueryable?

查看:65
本文介绍了在哪种情况下,我需要为IEnumerable和IQueryable创建两种不同的扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我需要一个扩展方法,该方法仅从不同来源中选择所需的属性.源可以是数据库或内存中的集合.所以我定义了这样的扩展方法:

 public IQueryable<TResult> SelectDynamic<TResult>(
            this IQueryable<T> source,
            ...)

这对于IQueryable s正常工作.但是,我还必须为IEnumerable s调用此函数.

在这种情况下,我可以借助.AsQueryable()来调用它:

  myEnumerable.AsQueryable()
        .SelectDynamic(...)
        .ToList();

两者都很好.而且,如果两种方法都能正常工作,在哪种条件下,我必须创建两种不同的扩展方法以达到相同的目的,一种用于IEnumerable,另一种用于IQueryable?

如果是Queryable,我的方法必须将查询发送到数据库.

例如,这是System.Linq命名空间中.Select扩展方法的来源:

我再次重复我的主要问题:

在使用Queryable的情况下,我的方法必须将查询发送到数据库,但使用IEnumerable时则不是.现在,我将AsQueryable()用于枚举.因为,我不想为Enumerable编写相同的代码. 它会产生一些副作用吗?

解决方案

myEnumerable.AsQueryable()返回自定义对象:new EnumerableQuery<TElement>(myEnumerable);(.Select for IEnumerable

  • .Select for IQueryable
  • I am repeating my main question again:

    My method must send query to the database in case of Queryable, but not when working with IEnumerable. And for now, I am using AsQueryable() for the enumerables. Because, I dont want to write same code for the Enumerable. Can it have some side effects?

    解决方案

    myEnumerable.AsQueryable() returns a custom object: new EnumerableQuery<TElement>(myEnumerable); (source code)

    This EnumerableQuery class implements IEnumerable<T> and IQueryable<T>

    When using the EnumerableQuery result of .AsQueryable() as an IEnumerable, the implementation of the interface method IEnumerable<T>.GetIterator() simply returns the original source iterator, so no change and minimal overhead.

    When using the result of .AsQueryable() as an IQueriable, the implementation of the interface property IQueriable.Expression simply returns Expression.Constant(this), ready to be evaluated later as an IEnumerable when the whole expression tree is consumed.

    (All the other methods and code paths of EnumerableQuery are not really relevant, when the EnumerableQuery is constructed directly from an IEnumerable, as far as I can tell)

    If I understand you correctly, you have implemented your method selectDynamic<TResult>() in such a way that you construct an expression tree inside the method, that produces the desired result when compiled.

    As far as I understand the source code, when you call e.g. myEnumerable.AsEnumerable().selectDynamic().ToList(), the expression tree you constructed is compiled and executed on myEnumerable, and the total overhead should be fairly minimal, since all this work is only done once per query, not once per element.

    So i think there is nothing wrong with implementing your IEnumerable Extension method like this:

    public IEnumerable<TResult> SelectDynamic<TResult>(
            this IEnumerable<T> source,...)
        return source.AsQueryable().SelectDynamic();
    }
    

    There is some slight overhead, since this compiles the query once each time this method is called, and I am not sure the JITer is smart enough to cache this compilation. But I think that will not be noticeable in most circumstances, unless you execute this query a thousand times per second.

    There should be no other side efects, apart from slight performance issues, in implementing the IEnumerable extension method in this way.

    这篇关于在哪种情况下,我需要为IEnumerable和IQueryable创建两种不同的扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆