IEnumerable作为返回值、延迟执行和 N 层应用程序
本文关键字:执行 延迟 应用程序 返回值 IEnumerable | 更新日期: 2023-09-27 17:56:16
首先,我不认为这个问题是这些SO问题的重复:
我应该总是返回 IEnumerable
众所周知,引入多层的主要目的是减少耦合。
我们必须为数据访问定义一些接口,我们的 BL 不应该关心 DAL 实现的细节。如果提到的接口返回IEnumerable<T>
则 BL 不知道它只是一个静态IEnumerable
还是延迟执行的东西。同时,这个特定的细节会极大地影响性能,并且需要根据实现进行不同的编码。
好吧,当我们要多次迭代集合时,可以为每个IEnumerable
调用.ToList()
。但是,由于不必要的新列表实例化,这会降低静态集合的性能。
所以我试图了解哪种方法更好。
更通用且性能可能更低,与更耦合的高性能相比。我想,没有灵丹妙药,但可能是我错过的其他方法。
所以我试图了解哪种方法更好:更通用、性能更低,与耦合度更高、性能更高。
首先,虽然这是一个有趣的权衡,但在这种情况下,我认为相关的权衡实际上是正确的与不正确的,这肯定胜过任何性能问题。延迟执行查询通常具有以下属性:它为您提供查询的最新结果,而调用ToList
则为您提供查询结果的过去版本的快照。肯定有一种是正确的,另一种是不正确的。
其次,假设您已经处理了正确性问题,并且确实需要进行性能权衡,那么您实际想要做出的权衡是:更普遍和不可接受的性能与更耦合和可接受的性能,很明显您必须选择性能可接受的性能。
如果两者都具有可接受的性能,并且一个比另一个慢几纳秒,或者比另一个多消耗几个字节的内存,并且两者都是正确的,那么谁在乎你选择哪一个呢?把你宝贵的时间花在思考别的事情上。如果两者都没有可接受的性能,那么你有一个更大的问题需要解决。
如果从概念上讲,调用方知道方法的返回类型是List
而不是IEnumerable
很重要(例如,知道多次迭代它不会产生负面影响),则应返回List
。 相反,返回接口的要点是一种说"实现是什么并不重要"的方式。 如果实现确实很重要,则不要使用该接口(在特定情况下)。
我找到了很好的解决方案:DAL 中的所有返回类型(in 接口)都不能IEnumerable<>
(或者不能是接口类型)。但它可以在BL中使用。这可能是架构师的决定。