Liskov-substitution 原则要求子类型必须满足超类型的契约。据我了解,这将ReadOnlyCollection<T>
违反 Liskov。 ICollection<T>
的合约暴露Add
和Remove
操作,但是只读子类型不满足这个合约。例如,
IList<object> collection = new List<object>();
collection = new System.Collections.ObjectModel.ReadOnlyCollection<object>(collection);
collection.Add(new object());
-- not supported exception
显然需要不可变的集合。.NET 的建模方式有问题吗?更好的方法是什么? IEnumerable<T>
在暴露集合方面做得很好,至少看起来是不可变的。然而,语义是非常不同的,主要是因为IEnumerable
没有显式地暴露任何状态。
在我的特殊情况下,我正在尝试构建一个不可变的DAG类来支持FSM。一开始我显然需要AddNode
/AddEdge
方法,但我不希望一旦它已经运行就可以更改状态机。我很难表示 DAG 的不可变和可变表示之间的相似性。
现在,我的设计涉及预先使用 DAG Builder,然后创建一次不可变图,此时它不再可编辑。Builder 和具体的不可变 DAG 之间唯一的通用接口是Accept(IVisitor visitor)
. 我担心面对可能更简单的选项,这可能是过度设计/过于抽象。同时,我无法接受我可以在我的图形接口上公开方法,NotSupportedException
如果客户端获得特定的实现,这些方法可能会抛出。处理这个问题的正确方法是什么?