Resharper,“返回类型可以是IEnumerable ……”但为什么呢?

我有这样的界面……

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

但Resharper建议我将其更改为IEnumerable FindByUserId(int userId)

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

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

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

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

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

答案是“不, 但是 ”。

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

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

这样做的结果是您传递的Lambda表达式将转换为Func而不是Expression>(请注意两个相应方法的参数列表中的差异)。 因此,您的lambda将不是表达式树,这是Queryable源所需要的,以便将其转换为SQL(或类似的),以便查询可以通过服务器和执行的服务器端传递。

所以,你的查询会更慢。 不是因为它会在你投射后执行,而是因为一旦你开始尝试从中获取项目,整个数据源就会被拉到客户端。

当然,这只是在此方法中使用LINQ(附加“Where”子句或其他内容)时。 如果你不这样做,你没事。

IQueryable已经从IEnumerable ( MSDN )inheritance,因此您对IEnumerable任何异议仍将存在。 ReSharper指示即使所有实现都返回IQueryable ,也可以定义该方法以返回IEnumerable (如果调用需要IQueryable而不是IEnumerable他们也可以调用AsQueryable MSDN )

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