Array.Add方法是否违反了LSP?

Ale*_*sev 4 .net c# oop liskov-substitution-principle solid-principles

Arrayclass实现IList具有Add成员的接口.Array.Add调用抛出NotSupportedException.这是违反Liskov替代原则还是接口隔离原则或两者兼而有之?

ana*_*der 6

这绝对违反了界面隔离原则.ISP声明组件应该仅依赖于它们实际需要的接口.Array实现IList,但显然不需要或不需要所有定义的方法IList,因为它选择抛出异常来解释它不支持Add.此外,任何需要Array现在的东西IList尽管不需要它的所有方法(因为任何想要数组的东西显然不担心Add,因为它无论如何都不起作用).不支持您的界面建议您实施的操作显然是ISP违规; 尽管不需要全部代码,强制消费代码依赖于接口也是ISP违规.

可能导致违反Liskov替代原则.如果代码依赖于a IList,则LSP声明它在传递任何实现时应该正常运行IList.但是,当传递a时Array,该代码现在会在它尝试调用时抛出异常Add.

这是否构成LSP违规取决于您如何看待LSP的异常.如果你从例外是预期合同的一部分的角度来看待它,那就没关系了.该方法符合其合同,并且在Add不考虑异常可能性的情况下调用的任何代码都是错误的.

如果你更多的意见NotSupportedException被认为是错误或失败,那么这是一个明显的LSP违规.就个人而言,我发现SOLID原则相互支持并且在真空中难以解决,因此使用接口隔离原则作为备份,我会说接口说"我可以做这些事情",所以说"实际上,我不能做那件事"是一个错误,因此可能不应被视为有效合同的一部分.如果异常不是合同的一部分,那么通过抛出一个,Array违反了Add合同,因此破坏了LSP.

  • @Fildor哦是的,没有发现那一点!但是因为这意味着它永远不能保证安全地调用`.Add()`这实际上意味着任何通过`IList`调用`.Add()`的方法都是等待发生的事故.将数组传递给接受`IList()`的方法,该方法没有明确地记录它不会调用`.Add()`因此是不正确的 - 这就是为什么这样的违规是如此糟糕的事情. (4认同)
  • 它甚至比这更糟糕,因为您可能认为至少可以使用`list.IsReadOnly`来检测列表是否不能调用`.Add()` - 但遗憾的是这个`list.IsReadOnly`对于数组类型是假的.如果调用以下方法并将数组传递给它,则返回false:`public static bool IsreadOnly(IList list){return list.IsReadOnly; }` (2认同)