将IQueryable.Count <T>与IEnumerable <T>参数一起使用

Rap*_*aus 15 c# linq ienumerable iqueryable

想象一个类,让我们说可以与一个IList<T>或一个一起使用的分页IQueryable<T>.

该类将具有一个int TotalItems属性,该属性(不是那么令人惊讶)获取/设置可查询或可枚举参数的计数.

如果我IEnumerable<T>用作参数,

//simplified
public Pagination(IEnumerable<T> query)
    {
        TotalItems = query.Count();
    }
Run Code Online (Sandbox Code Playgroud)

Count()方法将是(如果我没看错,这就是问题所在)Enumerable.Count().因此,即使查询是IQueryable<T>(继承自IEnumerable<T>),它也将被枚举(使用"db query"显然不需要).

那么有什么方法可以Queryable.Count()在我IEnumerable<T>实际使用时使用方法IQueryable<T>,或者我必须改变我的设计,例如在这种情况下,2 ctor

//simplified
public Pagination(IEnumerable<T> query)
    {
         TotalItems = query.Count();
    }
public Pagination(IQueryable<T> query)
    {
         TotalItems = query.Count();
    }
Run Code Online (Sandbox Code Playgroud)

编辑 我也明白,IQueryable<T>沿用IEnumerable<T>无关的事实,IEnumerable<T>IQueryable<T>具有相同的扩展名的方法,而且它的好,有延期的方法相同的名字,"看起来他们做同样的",但我认为它仍然有时令人困惑......

好奇心的一般问题

它们是框架中的其他示例,具有相同的"体系结构":继承+扩展方法的通用名称?

Ser*_*rvy 8

您应该有两个构造函数重载,正如您在问题中所示.这使得调用者无论他们是想要使用IQueryable方法还是要使用的IEnumerable方法.

如果有人这样做:

Pagination pager = new Pagination(query.AsEnumerable());
Run Code Online (Sandbox Code Playgroud)

然后他们显然希望将对象作为一个IEnumearble而不是一个处理IQueryable.也许他们知道Skip并且Take不是由他们的查询提供者实现的,因此分页将失败,并且需要将其评估为Linq-to-objects.

通过使用两个重载,您可以使您的类的用户知道他们是在处理内存序列还是查询,而不是试图自己解决它.