【问题标题】:Resharper, "Return type can be IEnumerable..." but why? [duplicate]Resharper,“返回类型可以是 IEnumerable...”,但为什么呢? [复制]
【发布时间】:2013-07-28 16:08:52
【问题描述】:

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

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

但 Resharper 建议我将其改为 IEnumerable&lt;Account&gt; FindByUserId(int userId)

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

【问题讨论】:

  • 在你执行.Count().ToList()等方法之前,它不会加载到内存中。
  • 这将是因为您的解决方案中没有对FindByUserId 返回的对象使用任何IQueryable&lt;T&gt; 方法,因此R# 建议您可以使返回类型更通用。
  • @Pierre-LucPineault IQueryable 允许进一步细化查询 (.Where...),而无需预先将结果加载到内存中的对象中。显然这不是 IEnumerable 的情况吧?
  • @RosdiKasim 你提出了一个很好的观点,我显然没有在我的回答中完全考虑到这一点。但是Where 方法是IEnumerable 上的扩展方法无论如何MSDN,所以你仍然没有失去任何权力(即使我不确定如何覆盖扩展方法)。还是我错过了IQuerable 的一些内容?
  • @Porges 你是对的,我的解决方案中没有使用IQueryable&lt;T&gt; 方法,但这并不意味着它将来不会被使用,对吧?还是我错过了什么?

标签: c# resharper


【解决方案1】:

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

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

在这种情况下,您只使用了IEnumerable&lt;T&gt; 接口的方法,IQueryable&lt;T&gt; 派生自该接口。

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

【讨论】:

  • +1 返回类型可以是IEnumerable只是表示返回类型可以IEnumerable而不是应该 是。
  • 谢谢.. 我只是想确保我了解自己在做什么,而不是盲目地遵循 R# 建议。
【解决方案2】:

答案是“不,但是”。

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

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

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

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

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

【讨论】:

  • 这意味着我可能会疯狂地将大量结果移动到内存中进行过滤,对吗?这就是我从这个答案中所理解的,stackoverflow.com/a/2876655/193634
  • 您在此方法中使用的任何 LINQ 运算符都将无法执行服务器端。
  • @RosdiKasim 如果您从存储库返回非常大的数据集,这是可能的,但您到底为什么要这样做? IQueryable 是一个泄漏的抽象,如果有的话,所以你想尽早限制结果集,只在服务层处理IEnumerables。
【解决方案3】:

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

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

【讨论】:

猜你喜欢
  • 2020-06-27
  • 2021-04-25
  • 2020-06-05
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多