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服务调用获得的,这些调用也只会在请求特定成员时进行。