Принцип Liskov-substitution требует, чтобы подтипы удовлетворяли контрактам супертипов. По моему мнению, это повлечет за собой нарушение ReadOnlyCollection<T>
Лискова. Контракт 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
, если клиент получает конкретную реализацию. Каков правильный способ справиться с этим?