为什么数组支持IList?

发布于 2024-08-04 00:42:21 字数 107 浏览 5 评论 0原文

IList 接口需要一个 Add 方法。数组实现了这个函数,但它只是抛出一个 NotImplementedException。对我来说这似乎是非常糟糕的设计。

设计师这样做时在想什么?

The IList interface requires an Add method. Arrays implement this function but it simply throws a NotImplementedException. This seems like very bad design to me.

What were the designers thinking when they did this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蹲在坟头点根烟 2024-08-11 00:42:21

IList 可以是只读的 - 如果有疑问,调用者可以在尝试添加或删除元素之前测试 IsFixedSize 属性,或者在尝试修改元素之前测试 IsReadOnly 属性。

数组是固定大小的 IList。

将数组视为列表会很方便。一个示例是模拟返回 IList 的数据访问方法 - 可以模拟它以简单地返回数组转换为 IList。

ILists can be readonly - if in doubt the caller can test the IsFixedSize property before attempting to add or remove an element, or the IsReadOnly property before attempting to modify an element.

An array is a fixed-size IList.

It can be convenient to be able to treat an array as a list. One example is mocking a data access method that returns an IList - it can be mocked to simply return an array cast as an IList.

寂寞花火° 2024-08-11 00:42:21

由于不同的对象通常具有不同的能力,因此某些接口包含将由某些但不是所有实现实现的成员。如果假设的接口 IVehicle 的某些(但不是全部)实现能够附加预告片,则典型的模式是将 AttachTrailer 的函数定义为“尝试如果 CanAttachTrailer 为 true,则附加预告片,否则抛出 NotSupportedException”。 IVehicle 的所有实现都能够符合上述规范,无论它们是否可以处理拖车。

这种方法的优点是接口的实现可以提供许多不同的功能组合,而不必为不同的组合定义不同的类型。此方法的另一个优点是,方法 Foo 接收包含 Foo 不需要的功能的对象,可以将该对象传递给方法 < code>Bar,它确实需要这些功能,不需要在任何地方进行任何类型转换,并且 Foo 也不知道 Bar 需要什么功能。另一个优点是,这使得编写不需要某些功能但可以在它们存在时利用它们的代码变得容易。

然而,这种方法也有一些缺点。接口还没有办法为任何属性或方法指定默认实现。因此,即使无法附加预告片的 IVehicle 实现也需要包含将 false 返回到 CanAttachTrailer 属性的代码,并在其 CanAttachTrailer 属性中抛出异常。代码> AttachTrailer方法。此外,由于接口不要求实现其许多方法,因此编译器无法知道拒绝尝试调用需要具有无法提供该功能的类型的对象的功能的函数。

在设计 IList 时,微软显然认为“可选功能接口”方法的优点超过了缺点。事实上,如果 .net 为实现接口的类提供了一种方法来遵循它们不希望提供的成员的默认实现,那么就没有理由不在基本级别接口中包含许多可选功能;为了允许编译时执行必要的功能,可以从包含所有所需成员的基派生出许多接口,并指定实现后一个接口的类必须以实际有用的方式实现某些成员。例如,Microsoft 可以定义 IResizableList 来继承 IList,而不添加任何成员,但期望 IList code> 允许调整大小的实现将实现后一个接口,而那些不允许调整大小的实现将不会实现它。如果他们这样做了,需要能够调整列表大小的代码可能需要一个 IRessizedList (在这种情况下,它不会接受数组),而不需要调整列表大小的代码列表可能需要一个 IList)。不幸的是,微软没有做类似的事情,所以代码不可能在编译时要求可调整大小的列表——如果传入的列表将自身报告为固定大小,它所能做的就是发出警告。

Because it is common for different objects to have different abilities, some interfaces include members which will be implemented by some but not all implementations. If some, but not all, implementations of a hypothetical interface IVehicle would be able to attach a trailer, a typical pattern would be to define the function of AttachTrailer as "Attempt to attach a trailer, if CanAttachTrailer is true, or else throw NotSupportedException". All implementations of IVehicle would be able to conform to the above specification, whether or not they can handle trailers.

An advantage of this approach is that it is possible for implementations of an interface to offer many different combinations of features, without having to define different types for different combinations. Another advantage of this approach is that it is possible for a method Foo which receives an object that includes capabilities that Foo doesn't need, to pass that object along to method Bar, which does need those capabilities, without requiring any typecasts anywhere, and without Foo knowing what capabilities Bar will need. Yet another advantage is that this makes it easy to write code which doesn't need certain capabilities, but can take advantage of them when they exist.

There are some disadvantages to this approach, however. There is as yet no way for an interface to specify default implementations for any properties or methods. Consequently, even IVehicle implementations which cannot attach trailers will need to include code to return false to the CanAttachTrailer property, and throw an exception in their AttachTrailer method. Further, since the interface imposes no requirement that many of its methods be implemented, there is no way a compiler can know to reject at attempt to call to a function that requires a capability with an object of a type which cannot provide it.

When designing IList<T>, Microsoft apparently thought that the advantages of the "optional-capabilities interface" approach outweighed the disadvantages. Indeed, if .net provided a means for classes implementing interfaces to defer to default implementations of members they don't wish to provide, there would be little reason not to include many optional capabilities in base-level interfaces; to allow compile-time enforcement of necessary capabilities, one could have a number of interfaces derive from a base which includes all the needed members, and specify that classes implementing the latter interfaces must implement certain members in ways that are actually useful. For example, Microsoft could have defined IResizableList<T> to inherit IList<T> without adding any members, but with the expectation that IList<T> implementations that allowed resizing would implement the latter interface, while those which did not allow resizing would not implement it. Had they done that, code which needed to be able to resize a list could demand an IResizableList<T> (in which case it would not accept an array), while code which did not need to resize a list could demand an IList<T>). Unfortunately, Microsoft didn't do anything like that, so it's not possible for code to demand a resizable list at compile time--all it can do is squawk if a passed-in list reports itself as fixed-size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文