返回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。
在退出保存DataContext
的using
块之前使用ToList
。
当调用者可能/有义务提供额外的过滤条件时,返回查询,索引将使用这些条件来减少结果行数和/或数据库IO。
如果需要结果对象列表,请使用ToList()
。