我有一个方法可以选择不同的对象集合,将它们添加到列表中然后返回列表。
最初该方法返回IEnumerable但是当它返回一个不同的集合时,我可以将不同的对象添加到一个hashset并返回ISet。
我很欣赏ISet使返回的对象可以修改(消费者可以添加()给它但是我还是要返回一个新列表,所以我认为这不会影响我,为什么我关心消费者做什么呢收藏一旦他们拥有它?
问题是,我应该这样做吗?或者我应该只返回IEnumerable并且很高兴它只包含不同的元素(目前通过测试保证)
答案 0 :(得分:2)
与以往一样,通过设计,您在这里有相互矛盾的要求。良好设计的艺术是在您正在创造的产品的这些要求之间选择最佳平衡。
界面设计的一个原则是您将界面视为合同或承诺。很明显,承诺或合同的规定性越低,就越容易保留。因此,返回类型IEnumerable<T>
意味着您承诺只返回一系列事物。 “更严格”或更衍生的类型将更具说明性,更难以保留。
反过来说,如果你在函数中工作以确保更多地返回类型,那么通过返回较少描述性的父类型来放弃该工作似乎是浪费。如果你已经有一个ISet<T>
,定义了一组事物,那就是明确的,返回那个并保存调用者不同检查的工作。
一般来说,没有简单的答案,正确的答案取决于来电者和您的系统。在一般情况下,我们不了解呼叫者。在没有证据的情况下,我们必须承担任何责任,并从弱势承诺中获取实际利益。因此,一般情况下,与IEnumerable<T>
一起使用,它可以为您提供更大的灵活性,现在没有已知成本。
在特定情况下,我们知道调用者将从集合的返回中受益。在这种情况下,会出现关于序列清晰度的错误。明确并返回ISet<T>
是有意义的,这有助于防止重复检查。要添加警告,只有每个可能的呼叫数据都是不同的,这才有意义。您必须确保您将为所有呼叫者保留承诺,而不仅仅是那些提出错误的人。
答案 1 :(得分:0)
在一个方法返回一系列唯一元素的情况下,为什么要查看你的问题就是“通过示例”?返回类型应该是什么?
BCL包含这样一种方法(你说明你正在使用),即Enumerable.Distinct<T>
该方法的返回类型是IEnumerable。那么为什么选择一个不在其中的类型自我预测实现将保留的所有承诺?我可以看到两个论点
接口IDistinctEnumerable会改变其中的任何一个吗?界面提供的唯一信息在名称中。类型系统可以确保运行时序列中的元素是唯一的,但因为它只是在名称中与我用于Distinct的参数基本相同。 如果从外部看到它是通过该方法返回一个集合所期望的,那么它可能会永远保持这种状态,然后返回一个集合可能是值得的。但是,一系列独特元素和一组之间存在差异。