简体   繁体   English

Array.Add 方法是否违反 LSP?

[英]Does Array.Add method violates LSP?

Array class implements IList interface that has Add member. Array类实现具有Add成员的IList接口。 Array.Add invocation throws NotSupportedException . Array.Add调用抛出NotSupportedException Is it a violation of The Liskov Substitution Principle or The Interface Segregation Principle or both of them?它是否违反了Liskov 替换原则接口隔离原则或两者?

This is definitely a violation of the interface segregation principle.这绝对违反了接口隔离原则。 ISP states that components should only depend on interfaces that they actually require. ISP 声明组件应该只依赖于它们实际需要的接口。 Array implements IList , but clearly does not need or want all of the methods defined by IList , because it chooses to throw an exception to explain that it doesn't support Add . Array实现了IList ,但显然不需要或不需要IList定义的所有方法,因为它选择抛出异常来说明它不支持Add Furthermore, anything that needs an Array now has an IList despite not needing all of its methods (because anything that wants an array is clearly not worried about Add , since it doesn't work anyway).此外,任何需要Array东西现在都有一个IList尽管不需要它的所有方法(因为任何需要数组的东西显然都不担心Add ,因为它无论如何都不起作用)。 Not supporting an operation that your interface suggests that you implement is clearly an ISP violation;不支持您的界面建议您实施的操作显然是违反 ISP 的; forcing consuming code to depend on an interface despite not needing all of it is also an ISP violation.尽管不需要所有接口,但强制使用它的代码依赖于接口也是违反 ISP 的。

This can lead to a violation of the Liskov substitution principle.可能会导致违反 Liskov 替换原则。 If code depends on an IList , LSP states that it should function correctly when passed any implementation of IList .如果代码依赖于IList ,则 LSP 声明它在传递IList任何实现时应该正确运行。 However, when passed an Array , that code will now throw an exception any time it tries to call Add .但是,当传递Array ,该代码现在将在尝试调用Add时抛出异常。

Whether this constitutes an LSP violation depends how you see exceptions with respect to LSP.这是否构成 LSP 违规取决于您如何看待有关 LSP 的异常。 If you approach it from the viewpoint that the exceptions are a part of the expected contract, then it's fine.如果您从例外是预期合同的一部分的角度来处理它,那很好。 The method conforms to its contract, and any code that calls Add without accounting for the possibility of an exception is at fault for not doing so.该方法符合其约定,任何调用Add而不考虑异常可能性的代码都因不这样做而出错。

If you're more of the opinion that NotSupportedException is considered an error or failing, then it's a clear LSP violation.如果您更NotSupportedException认为NotSupportedException被视为错误或失败,那么这显然违反了 LSP。 Personally, I find that the SOLID principles support each other and are harder to address in a vacuum, so using the interface segregation principle as backup, I'd say that the interface says "I can do these things", so saying "actually, I can't do that thing" is an error, and therefore probably shouldn't be considered part of a valid contract.我个人觉得SOLID原则是相互支持的,很难在真空中解决,所以使用接口隔离原则作为备份,我会说接口说“我可以做这些事情”,所以说“实际上,我不能做那件事”是一个错误,因此可能不应被视为有效合同的一部分。 If the exception isn't part of the contract, then by throwing one, Array is violating Add 's contract, and is therefore breaking LSP.如果异常不是合同的一部分,那么通过抛出异常, Array违反了Add的合同,因此破坏了 LSP。

The Liskov Substitution Principle - Liskov 替换原则-

A program that uses an interface must not be confused by an implementation of that interface.使用接口的程序不得与该接口的实现混淆。

Arrays make an exception in case of implementation IList<> - that is confused.数组在实现 IList<> 的情况下是一个例外 - 这是混淆的。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM