Q1 为什么.NET中的新类仅部分实现接口?
Q2 我会在代码中执行相同操作吗?
我问了这个问题here,所以我想,好吧很久以前,你可以有不同的用法等等,现在这种实现只是出于一致性原因而受支持。但新课程也是如此。
旧
int[] list = new int[] {};
IList iList = (IList)list;
ilist.Add(1); //exception here
新
ICollection c = new ConcurrentQueue<int>();
var root = c.SyncRoot; //exception here
更新
我并不担心为什么我得到例外,很明显。但我不明白为什么类实现明确定义的合同,但不是所有成员(这可能会导致令人不快的运行时异常)?
答案 0 :(得分:4)
您可能会认为接口在原始设计中不够精细。例如,大多数人 从不使用 SyncRoot
- 它可能已经在不同的界面上。同样,不幸的是,没有接口提供只读索引器访问,例如。
就目前而言,接口就是它们的本质。实现主IList[<T>]
/ ICollection[<T>]
/ IEnumerable[<T>]
接口仍然非常方便 - 它提供了多数的呼叫者访问他们需要的东西...第一个示例中为 indexers ,第二个示例中为Add
。
公平地说,他们还提供IsFixedSize
和IsReadOnly
- 查询第一个会导致您不致电Add
。 Re SyncRoot
- 在ConcurrentQueue<T>
内可能没有意义,任何实现都会破坏该类型的逻辑。通常我会说“那么它不是那种类型;不要实现界面”,但要重复我之前的陈述...... 大多数人从不使用SyncRoot
< / strong> - 所以我很好; p
答案 1 :(得分:2)
一个小问题,所有接口都必须完全实现。接口的所有方法和属性必须由任何实现者实现 - 否则编译器。您指的是在调用接口的某些方法时可能引发的运行时错误。
IList
州的文档:
IList是ICollection接口的后代,是所有非泛型列表的基本接口。 IList实现分为三类:只读,固定大小和可变大小。无法修改只读IList。固定大小的IList不允许添加或删除元素,但它允许修改现有元素。可变大小的IList允许添加,删除和修改元素。
当您调用某个特定实现无法满足的方法时,您会收到异常。
为什么界面是这样设计的?人们只能推测,但这种特殊设计允许在接口实例的生命周期内更改IsFixedSize
,IsReadOnly
等属性。
你应该用这种方式设计界面吗?这取决于这种设计是否合乎需要并满足您的需求。
答案 2 :(得分:1)
从OOP的角度来看,这是完全错误的。他们应该制作更小的接口,或者不要把它们放在像Arrays这样的东西上。但是,.NET Framework设计人员并不愚蠢,他们可能会做出一些权衡。例如,IEnumerable需要实现IDisposable,这从OOP设计的角度来看是没有意义的,但是例如,数据库读取器有一些性能优势。所以可能被黑客入侵的类(如你的例子)有一些好处,但从OOP的角度来看它们是错的,你不应该这样做,除非你知道你正在交易好的设计。
答案 3 :(得分:0)
我怀疑部分实现的接口的存在是设计决定不允许类或接口具有相同名称的独立可读属性和可写属性并自动适当地使用它们的结果(例如,如果类具有可读属性'foo'和可写属性'foo',使用可读属性进行读取,使用可写属性进行写入)。这个设计决定使得分离某些接口的读写方面变得尴尬。
理想情况下,不存在单个接口IList,而是存在通用逆变接口IReadableByIndex,通用协变接口IWriteableByIndex,IAppendable,IGrowableByIndex(包括各种插入和删除功能),以及非通用IMovableByIndex(基于索引的副本,交换和滚动功能)和IComparableByIndex(给定两个索引,比较项目)。一个接口IList可以实现所有这些,但也会有许多有用的子集(其中许多可能是逆变或协变)。请注意,某些非泛型例程的存在将允许在任何实现IComparableByIndex和IMovableByIndex的集合上实现类似的事情,而不必担心集合的确切类型。
不幸的是,由于IList的拆分非常有用,因此必须将IReadableByIndex和IWritableByIndex作为单独的接口。这反过来会在尝试编写将继承两个接口的代码时造成困难,因为编译器在尝试使用索引访问器时会抱怨模糊性。由于IReadableByIndex和IWritableByIndex最终必须合并,微软可能认为它可能会将所有内容整合到IList中。