我目前正在编写一个简单的数据访问层,我想知道应该向其他层公开哪种类型。
我将在内部将数据实现为 List<>,但我记得读过一些关于在不需要时不将 List 类型公开给消费者的内容。
public List<User> GetAllUsers() // non C# users: that means List of User :)
你知道为什么(谷歌没有帮助)?你通常会为那种东西暴露什么?列表?可数?
我目前正在编写一个简单的数据访问层,我想知道应该向其他层公开哪种类型。
我将在内部将数据实现为 List<>,但我记得读过一些关于在不需要时不将 List 类型公开给消费者的内容。
public List<User> GetAllUsers() // non C# users: that means List of User :)
你知道为什么(谷歌没有帮助)?你通常会为那种东西暴露什么?列表?可数?
通常最好公开用户仍然可以有意义地使用的最不强大的界面。如果用户只需要一些可枚举的数据,返回IEnumerable<User>
. 如果这还不够,因为用户需要能够修改列表(注意!不应该经常这样),返回一个IList<User>
.
Joel 在他的评论中提出了一个有效的问题:为什么确实公开最不强大的界面而不是授予用户最大的权力?(转述)
这背后的想法是返回数据的方法可能不希望用户修改其内容:该类的另一个方法可能仍然希望列表在返回对它的引用后不为空。想象一下,用户从列表中删除了所有数据。另一种方法现在必须额外检查 ele 可能是不必要的。
更重要的是,这通过返回类型公开了部分内部实现。如果将来我需要更改实现以使其不再使用IList
容器,我有一个问题:我要么需要更改方法契约,要么引入构建中断的更改。或者我需要将数据复制到列表容器中。
例如,假设一个有效的实现使用 Dictionary 并且只返回Values
没有实现的集合IList
。
绝对是 ISomething。使用接口将减少耦合,并使更改数据层实现的细节变得更容易。哪个接口视情况而定。IList 很好,但有时您可能需要 ICollection 功能或想要指定只读值。
在返回 IEnumerable 之前,您应该仔细考虑。如果底层代码使用“yield”来生成 IEnumerable,或者使用 LINQ,那么您最终将保持打开所有使用的资源。
您应该在返回之前将 IEnumerable 复制到另一个 IEnumerable 中。通过使用 IList,您可以将此作为一项要求,这样任何人都不会无意中返回一个 IEnumerable。
另一方面,返回 IList 意味着调用者可以更改返回的列表。