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

时间:2013-07-27 22:58:02

标签: c# resharper

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

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

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

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

3 个答案:

答案 0 :(得分:8)

这只是一般规则的具体实例。

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

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

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

答案 1 :(得分:6)

答案是“不,但是”。

将其强制转换为IEnumerable不会强制执行。 IEnumerable空间中的运算符(如“Where”方法)仍然可以被懒惰地评估。

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

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

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

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

答案 2 :(得分:1)

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

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