История вопроса:
Коллекции Queue и Stack – это базовые структуры данных, реализующие соответственно принципы FIFO (First-In-First-Out) и LIFO (Last-In-First-Out). Их активно используют с эпохи классического VB6, а с приходом VB.NET эти структуры стали стандартными классами. Queue полезна для сценариев, где элементы должны обрабатываться в порядке поступления (например, очередь задач), а Stack — когда последний добавленный элемент требуется обработать раньше остальных (например, стек вызовов или отмена действий).
Проблема:
Часто ошибочно выбирают не ту структуру для определённой задачи либо используют их небезопасно в многопоточных сценариях. Также встречаются ошибки с извлечением пустого стека или очереди, что вызывает исключения.
Решение:
В Visual Basic для работы с этими структурами существуют соответствующие классы:
System.Collections.QueueSystem.Collections.StackПример работы с очередью и стеком:
' Работа с очередью Dim q As New Queue() q.Enqueue("Первый") q.Enqueue("Второй") Dim item = q.Dequeue() ' item = "Первый" ' Работа со стеком Dim s As New Stack() s.Push("A") s.Push("B") Dim top = s.Pop() ' top = "B"
Ключевые особенности:
1. Можно ли изменять коллекцию Queue или Stack в процессе итерации по ней с помощью For Each?
Нет, изменение (добавление или удаление элементов) коллекции в процессе обхода её с помощью For Each приводит к InvalidOperationException.
Пример кода:
Dim q As New Queue() q.Enqueue(1) q.Enqueue(2) For Each elem In q q.Enqueue(3) ' вызовет исключение во время итерации Next
2. Что вернет метод Peek() для пустого Queue или Stack?
Peek выбрасывает исключение InvalidOperationException, если коллекция пуста, а не возвращает значение по умолчанию.
Пример кода:
Dim st As New Stack() Dim first As Object = st.Peek() ' Exception!
3. В чем отличие Queue(Of T) от Queue и почему стоит отдавать предпочтение обобщённым коллекциям?
Queue(Of T) является дженерик-версией Queue, она типобезопасна и позволяет избежать boxing/unboxing. Лучше всегда выбирать её при работе с известными типами.
Dim numbers As New Queue(Of Integer)() numbers.Enqueue(5) ' Только Integer
В приложении, где реализована очередь печати документов, разработчик хранит задания на печать в Stack, а не в Queue. Как следствие, документы печатаются в обратном порядке (к последнему добавленному первыми обращаются).
Плюсы:
Минусы:
Тот же проект изменяет Stack на Queue для хранения заданий печати. Теперь документы печатаются по очереди слева направо, как ожидает пользователь.
Плюсы:
Минусы: