简短问题: 声明 data-object 的属性为 IEnumerable
是否可以,或者应该使用 Array
?
背景:
我刚刚在我们的项目中发现了一个导致性能问题的 bug。原因是 IEnumerable 被多次遍历。但这只是表面上看起来很简单。我认为那里存在设计缺陷,才会导致这种情况发生。
更深入的调查显示,一个名为GetAllUsers
的方法返回了一个UsersResponse
对象,其中一个属性是IEnumerable<T> UsersList
。当实现缓存时,很明显整个UsersResponse
对象被缓存了,并且在那个时候它能够正常工作,因为GetAllUsers
将一个数组分配给了IEnumerable<T> UsersList
。后来,GetAllUsers
的实现发生了改变,由于某种原因开发人员决定ToArray()
调用是多余的。所以我认为问题在于UsersResponse
对象设计不良,允许其工厂方法过于自由。另一方面,在原则上,缓存包含IEnumerable
属性的对象也是无用的。
因此,我们回到了关于设计数据对象的一般问题:当你声明它时,不知道它将来是否会被缓存或者除了当前需求之外还将如何使用,是否可以将其属性声明为IEnumerable
,将谨慎使用的责任放在其他开发人员身上,还是必须从一开始就声明为Array
?
我搜索过的内容:
我找到的唯一建议是Jon Wagner的博客文章,他建议尽快“封装”LINQ链。但这更涉及构建IEnumerable而不是将其存储在实体属性中。虽然与尽可能返回特定类型的原则相结合,它可以意味着将属性声明为Array
。
IEnumerable<T>
而不是IQueryable<T>
?如果使用某种远程 API,IEnumerable
和array
都将被传递到客户端的内存中。这只取决于你想要做什么。例如,如果你想在集合中使用 LINQ 进行查询,那么IEnumerable
可能更容易查询。如果你想要对集合中的任何元素进行O(1)
访问,则数组似乎是更好的选择。对我来说,区别只在于你打算如何使用它。 - oleksii