为SO写了另一个问题,我找到了一个我经常使用的模式,我从未真正反思过。但现在,我不再确定这是否正确:
如果我有我的WPF控件将绑定的集合,我几乎总是返回IEnumerable<SomeType>
。但在内部,这在大多数情况下是ReadOnlyObservableCollection<SomeType>
。我从来没有遇到过这个问题,并且所有消耗控件总是正确更新,因为它们检查INotifyCollectionChanged
- 接口,所以并不令人惊讶。
但我现在的问题是,如果这是不好的做法,只在签名中声明IEnumerable<SomeType>
,但要返回(并且还依赖)更强大的东西(INotifyCollectionChanged
)。
更新
我试着澄清:
我的主要目的是返回IEnumerable<SomeType>
。但大多数情况下,返回的IEnumerable<SomeType>
实现INotifyCollectionChanged
也会ReadOnlyObservableCollection<SomeType>
。消费控制相应地绑定(我的第二个意图是什么)。
也许我应该问:是否有一个完全包含IEnumerable和INotifyPropertyChanged的接口。
答案 0 :(得分:4)
请记住,IEnumerable<T>
和INotifyCollectionChanged
都是接口 - 它们不是确定类型。您可以设计具体的类来实现它们,没有任何问题。您的API可以返回方法调用的相应接口。事实上,这是一个很好的设计 - 不是要避免的事情。
ObservableCollection<T>
执行此操作(间接通过Collection<T>
),并实现IList<T>
以及其他接口。
如果您要制作自己的自定义集合,并计划将其与数据绑定一起使用,我会将其设为IEnumerable<T>
(或者可能IList<T>
,如果适用)和INotifyCollectionChanged
。这将使其具有最佳的可用性,无论是代码还是高效绑定。
(也依赖于)
但是,根据存在的不属于API的接口是不好的做法。这很危险,返回接口而不是具体类型的部分原因是允许实现稍后更改。通过对未声明的接口进行依赖,您的代码将变得脆弱。
话虽这么说,我经常做你正在尝试的事情,但这不是一种“硬”依赖。相反,我使用IEnumerable<T>
和检查 INotifyCollectionChanged
- 如果已实施则利用它。但是,如果“辅助”接口不存在,我会允许代码工作。
答案 1 :(得分:2)
返回最小界面而不是更丰富的界面通常是个好主意。如果你有一个丰富的界面,有更多的东西需要测试,而且可能出错的东西也越多。这也意味着如果您想避免破坏更改,您必须始终在可预见的将来支持所有这些额外功能。这使得以后修改实现变得更加困难。
然而,取决于界面无法保证的东西是一种不好的做法。如果有一天你没有得到ObservableCollection
但是得到其他类型的集合,那么代码将在运行时而不是在编译时失败。
答案 2 :(得分:2)
我倾向于认为,如果只有INotifyCollectionChanged
是正确的,那么您不希望只返回IEnumerable
这非常类似于返回Object
您真正想要的地方是MemoryStream.
当然,你可以转换回你需要的类型,但是如果稍后会出现一些,请参阅IEnumerable
的返回类型并编写与该返回相匹配但未实现INotifyCollectionChanged
的代码。 1}}?
答案 3 :(得分:1)
忘记WPF的数据绑定,然后确定什么是最好的返回,IEnumerable<T>
或更多concrette类型。由于WPF使用反射来确定如何绑定到指定集合的最佳方式,因此您不必担心。
答案 4 :(得分:0)
如果这是不好的做法,只在签名中声明
IEnumerable<SomeType>
但要返回(并且还依赖)更强大的东西(INotifyCollectionChanged
)
选择返回值类型以允许值使用者使用该值而不使用不安全的类型转换。
IEnumerable
,则值使用者不应该假设它是一个集合,还是一个可以更改的集合,或者它是一个可以更改的集合,并且可以通知它的更改。使用IEnumerable
的唯一方法是枚举它!没有办法确定某些内容会发生变化,应该再次枚举!
ReadOnlyObservableCollection
,则值使用者可以自由地假设它是一个集合,并且可以通知它的更改。 ReadOnlyObservableCollection
值使用者可以枚举该集合,也可以订阅更改通知,稍后在收到通知时再次枚举该集合。
最好在IEnumerable
界面下返回一些复杂的集合。
将 IEnumerable
用作INotifyPropertyChanged
或转换 IEnumerable
到INotifyPropertyChanged
或更多内容是不好的做法复杂。
是否存在完全包含
的界面IEnumerable
和INotifyPropertyChanged
很遗憾没有这样的界面,只有班级ReadOnlyObservableCollection
。