返回LINQ结果时何时调用ToList的经验法则

我正在寻找在IEnumerables上调用ToList/ToArray/MemoizeAll(Rx)的经验法则,而不是在返回IEnumerable时返回查询本身。

通常我发现最好只返回查询并让调用者决定是否需要列表,但有时它会因为linq的惰性而回来并咬你。

我想收集指南,例如:

调用ToList如果:

  • 你创建新的对象(例如在选择中)
  • 您的查询中有副作用

否则,返回查询

首先,你不应该在查询中有副作用。 这是最糟糕的做法。 查询应该回答一个问题,而不是产生影响。

您的问题的答案是:当调用者期望查询时返回查询; 当调用者期望列表时返回一个列表。 在设计方法时,确定调用者更可能需要的内容,实现该方法,然后对其进行记录

在考虑调用者是否需要查询或列表时,请考虑查询和列表之间的差异:

  • 查询始终是最新的。 如果对象/数据库/查询查询的内容更改其内容,则再次运行查询时查询结果将更改。 列表不会更改其内容,因此列表已过期 。 如果您的呼叫者需要最新数据,请给他们一个查询。 如果他们需要他们可以在闲暇时检查的数据快照,那么给他们一个清单。

  • 查询执行以获得结果可能很昂贵。 列表很便宜,无法获得结果。 如果调用者可能想要多次询问结果并希望每次都得到相同的结果,那么给他们一个列表。

  • 构建查询很快 。 执行查询以构造列表很 。 列表始终获取查询的所有结果。 调用者可能希望进一步限制查询,例如,仅采用前十个元素。 如果调用者不想要或者需要承担完全迭代整个查询的费用,那么给他们一个查询; 不要代表他们做出决定并给他们一份清单。

  • 查询很小 。 列表很大 。 可以在O(1)空间中的n个项上迭代许多查询; 包含n个项目的列表占用O(n)空间。 如果结果集很大,那么将它放在列表中可能效率很低。

  • 等等。

没有简单的答案。 答案与任何其他设计问题的答案相同: 在function用户最可能需要的内容中考虑每种可能解决方案的所有优缺点,然后选择合理的折衷解决方案。

返回ToList如果:

  • 您不希望或不关心延迟查询评估。

编辑:

此外,返回ToList如果:

  • 您正在使用某种Linq to SQL框架(LLBLGen,EF等),并且您需要在列表上执行操作,该操作无法通过框架转换为SQL。

如果需要对LINQ to SQL返回的数据运行自定义函数,请使用ToList。

在退出保存DataContextusing块之前使用ToList

当调用者可能/有义务提供额外的过滤条件时,返回查询,索引将使用这些条件来减少结果行数和/或数据库IO。

如果需要结果对象列表,请使用ToList()