6

我有一个这样的界面......

public interface IAccountRepository : IDisposable {
    IQueryable<Account> FindByUserId(int userId); //here, Resharper says "Return type can be IEnumerable<Account>"
}

但 Resharper 建议我改为IEnumerable<Account> FindByUserId(int userId)改为。

为什么呢?它不会强制将整个对象加载到内存中吗?我认为将执行推迟到真正需要对象时会更好吗?

4

3 回答 3

9

这只是一般规则的一个特定实例。

如果您要返回SomeClass实现接口或从另一个类继承的类型,并且在整个解决方案中,您只使用基类/接口中返回的对象上的方法(因此您不使用在 中声明的任何方法SomeClass), ReSharper 会建议您将返回对象的类型替换为基类/接口的类型,以使您的代码更通用。

在这种情况下,您只使用派生自的IEnumerable<T>接口的方法。IQueryable<T>

另请注意,这只是一个建议,而不是警告或错误。如果你愿意,你可以放心地忽略它。

于 2013-07-28T03:14:53.270 回答
6

答案是“不,但是”。

将其转换为 IEnumerable 不会强制执行。IEnumerable 空间中的运算符(如“Where”方法)仍然可以延迟计算。

但这里有一些警告。如果您在此方法中开始使用 LINQ 运算符,则 LINQ 将选择像GroupBy (IEnumerable)这样的 Enumerable LINQ 运算符,而不是像GroupBy (IQueryable)这样的 Queryable 运算符。请注意,它们的参数列表不同。

这样做的效果是您传递的 Lambda 表达式将被转换为 Func 而不是 Expression>(注意两个各自方法的参数列表中的差异)。所以你的 lambda 不会是一个表达式树,这是 Queryable 源需要的,以便将其转换为 SQL(或类似的),以便查询可以通过服务器传递并在服务器端执行。

因此,您的查询会变慢。不是因为一旦你转换它就会执行,而是因为一旦你开始尝试从中获取项目,整个数据源就会被拉到客户端。

当然,这仅在此方法中开始使用 LINQ(附加“Where”子句或其他内容)时。如果你不这样做,你很好。

于 2013-07-28T05:29:03.463 回答
1

IQueryable已经继承自IEnumerable( MSDN ),因此您必须提出的任何异议IEnumerable仍然存在。ReSharper 表示IEnumerable即使所有实现都返回,该方法也可以定义为返回IQueryable(如果调用需要 anIQueryable而不是他们也IEnumerable可以调用MSDNAsQueryable

此外,IEnumerable仅在枚举成员时才检索它们,这意味着即使每个成员都是通过单独的 Web 服务调用获得的,这些调用也只会在请求特定成员时进行。

于 2013-07-27T23:25:24.040 回答