Почему в .NET Framework отсутствует интерфейс IQueue <T> или IStack <T>?
Я хотел написать объект, работающий на подобном очереди интерфейсе. Я пошел искать IQueue<T>
, но вернулся неожиданно с пустыми руками.
Существуют следующие интерфейсы, связанные с коллекцией:
-
ICollection<T>
-
IList<T>
-
IDictionary<TKey,TValue>
-
ISet<T>
Что привело к тому, что эти типы коллекций получили четко определенные интерфейсы? Почему стеки и очереди не требуют интерфейса?
Ответы
Ответ 1
Хорошо, потому что между этими интерфейсами можно было бы сопоставить один-на-один для классов, которые их реализуют (кроме последних ConcurrentQueue
). Но другие упомянутые интерфейсы имеют множество классов, которые их реализуют.
Разверните бит. Мы не можем знать настоящую мотивацию команды BCL. Но у меня есть ощущение, что когда они создали Queue
и Stack
, эти классы выглядели настолько тривиальными, что они решили не абстрагировать их на интерфейсы. Причина очевидна: классы выглядели так просто, но в то же время были полными, поэтому не было причин создавать разные реализации в BCL. Затем наступил ConcurrentQueue
, и предыдущее утверждение немного изменилось.
Как он указал, Queue
и ConcurrentQueue
не так много похожи, чтобы они реализовали единый интерфейс.
Ответ 2
Я бы предположил, что вы не видите интерфейсы Stack или Queue из-за природы коллекций. Интерфейсы коллекции, которые вы указали, которые имеют интерфейсы, представляют собой произвольный доступ, а Stacks и Queues - нет. Они должны быть доступны в особой манере (FIFO или LIFO) и поэтому не могут использоваться в целом. Поэтому имеет смысл просто использовать эти коллекции в качестве общих реализаций, но не через интерфейсы. Другими словами, из-за ограничений, которые LIFO/FIFO помещает в коллекцию, очень мало (или ничего), которые могут быть сделаны по-разному классом, который реализовал теоретический IStack или IQueue.
Чтобы реализовать эту идею, вы можете создать свой собственный IStack и/или IQueue, а затем реализовать их в классе. Вы увидите, что функциональность, которую вы открываете, будет полностью сквозной. Например. В итоге вы просто перенаправляете или возвращаете запросы и результаты во внутреннюю коллекцию Stack или Queue. И в этой сквозной функциональности будет мало или вообще ничего потенциально добавлено.
Ответ 3
Почему платформа .NET должна иметь интерфейсы IQueue<T>
и IStack<T>
? Что они покупают?
Что сделали эти типы коллекций получить четко определенные интерфейсы?
Библиотеки базового класса фактически используют все эти интерфейсы (IList
и т.д.): в каждом случае есть группа других классов, для которых было более разумно взаимодействовать с абстракцией интерфейса, чем конкретный тип.
Почему стеки и очереди не требуют интерфейс?
Вероятно, потому что не было никаких классов BCL, которые нуждались в IStack<T>
и IQueue<T>
, и для этих абстракций не было очевидных или вероятных случаев использования.
Я понимаю, что это не удовлетворительный философский ответ, но похоже, что дизайнеры фреймворков были действительно прагматичны в отношении того, что получило интерфейсы: они сделали их, когда им были нужны.
Ответ 4
Я думаю, что, поскольку Stack и Queue - это очень специальные понятия, и, насколько мне известно, других классов не реализуется специальная форма стека или очереди.
EDIT:
Хорошо, теперь есть ConcurrentQueue<T>
, что, похоже, отрицает мой вывод. Возможно, еще во времена, когда С# 1.0 все еще находился в стадии бета-тестирования, разработчики языка думали, что никогда не будет особой формы очереди/стека, и теперь уже слишком поздно, чтобы представить для нее интерфейс.
Это много догадок. Надеюсь, Эрик Липперт увидит этот вопрос и опубликует "официальное" выражение.: -)
Ответ 5
Я думаю, что само существование новых классов в .NET 4 ConcurrentQueue<T>
и ConcurrentStack<T>
доказывает вашу точку зрения, что должны быть интерфейсы IQueue<T>
и IStack<T>
. Даже если они не существовали первоначально, их нужно было добавить в .NET 4.
Мне пришлось создавать собственные собственные реализации Stack в прошлом в .NET и соглашаться с тем, что использование стандартного интерфейса было бы полезным.
Ответ 6
Я сомневаюсь, что была какая-то особая причина. Если бы у меня были мои druthers, было бы намного больше дискретно определенных интерфейсов, даже если бы не были классы, которые реализовали их в одиночку. Например, я мог бы реализовать QueueStack (Of T), который будет реализовывать IGetNext (Of T), IGetNextWait (Of T) и IClear (Of T), а также IQueue (Of T), IWaitQueue (Of T), IStack (Of T) и IWaitStack (Of T). Люди, потребляющие объект, могли бы точно указать, что именно они на самом деле необходимы, и исполнители должны были только реализовать то, что они утверждают, чтобы поддерживать.