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

Does Array.Add method violates LSP?

Array class 实现具有 Add 成员的 IList 接口。 Array.Add 调用抛出 NotSupportedException。是否违反了里氏替换原则接口隔离原则或两者都违反?

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

可以导致违反里氏替换原则。如果代码依赖于 IList,LSP 声明在传递 any 实现 IList 时它应该正常运行。但是,当传递一个 Array 时,该代码现在将在任何时候尝试调用 Add.

时抛出异常

这是否构成 LSP 违规取决于您如何看待 LSP 的例外情况。如果您从例外是预期合同的一部分的角度来处理它,那很好。该方法符合其约定,任何调用 Add 而不考虑异常可能性的代码都是不这样做的错误。

如果您更倾向于将 NotSupportedException 视为错误或失败,那么这显然违反了 LSP。就个人而言,我发现 SOLID 原则相互支持并且很难在真空中解决,所以使用接口隔离原则作为备份,我会说接口说 "I can do these things",所以说 "actually, I can't do that thing"是一个错误,因此可能不应被视为有效合同的一部分。如果异常不是合同的一部分,那么通过抛出一个,Array 违反了 Add 的合同,因此违反了 LSP。

里氏替换原则 -

A program that uses an interface must not be confused by an implementation of that interface.

数组在实现 IList<> 时出现异常 - 这很混乱。

void Main() 
{ 
    var arr = new int[]{1,2,3}; 

    Test(arr);  
    
    void Test(IList<int> list)
    {
        list.Add(4);
    }
}