Historia pytania:
Kolekcje Queue i Stack to podstawowe struktury danych, które według zasad FIFO (First-In-First-Out) i LIFO (Last-In-First-Out) są odpowiednio zaimplementowane. Są one szeroko stosowane od czasów klasycznego VB6, a od pojawienia się VB.NET te struktury stały się standardowymi klasami. Queue jest przydatna w scenariuszach, gdzie elementy muszą być przetwarzane w kolejności przybycia (np. kolejka zadań), a Stack — gdy ostatnio dodany element musi być przetworzony przed innymi (np. stos wywołań lub cofanie działań).
Problem:
Często błędnie wybiera się niewłaściwą strukturę dla danej zadania lub używa się ich w sposób niebezpieczny w scenariuszach wielowątkowych. Pojawiają się również błędy związane z wydobywaniem z pustego stosu lub kolejki, co powoduje wyjątki.
Rozwiązanie:
W Visual Basic do pracy z tymi strukturami istnieją odpowiednie klasy:
System.Collections.QueueSystem.Collections.StackPrzykład pracy z kolejką i stosem:
' Praca z kolejką Dim q As New Queue() q.Enqueue("Pierwszy") q.Enqueue("Drugi") Dim item = q.Dequeue() ' item = "Pierwszy" ' Praca ze stosem Dim s As New Stack() s.Push("A") s.Push("B") Dim top = s.Pop() ' top = "B"
Kluczowe cechy:
1. Czy można zmieniać kolekcję Queue lub Stack w trakcie iteracji po niej za pomocą For Each?
Nie, zmiana (dodawanie lub usuwanie elementów) kolekcji w trakcie jej przeglądania za pomocą For Each prowadzi do InvalidOperationException.
Przykład kodu:
Dim q As New Queue() q.Enqueue(1) q.Enqueue(2) For Each elem In q q.Enqueue(3) ' spowoduje wyjątek podczas iteracji Next
2. Co zwróci metoda Peek() dla pustego Queue lub Stack?
Peek wyrzuca wyjątek InvalidOperationException, jeśli kolekcja jest pusta, a nie zwraca wartości domyślnej.
Przykład kodu:
Dim st As New Stack() Dim first As Object = st.Peek() ' Wyjątek!
3. Jaka jest różnica między Queue(Of T) a Queue i dlaczego warto preferować kolekcje ogólne?
Queue(Of T) jest wersją generyczną Queue, jest typowo bezpieczna i pozwala uniknąć boxing/unboxing. Zawsze lepiej jest wybierać ją przy pracy z określonymi typami.
Dim numbers As New Queue(Of Integer)() numbers.Enqueue(5) ' Tylko Integer
W aplikacji, w której wdrożono kolejkę drukowania dokumentów, programista przechowuje zadania drukowania w Stack, a nie w Queue. W rezultacie dokumenty są drukowane w odwrotnej kolejności (ostatni dodany jako pierwszy jest przetwarzany).
Plusy:
Minusy:
Ten sam projekt zmienia Stack na Queue do przechowywania zadań drukowania. Teraz dokumenty są drukowane po kolei od lewej do prawej, zgodnie z oczekiwaniami użytkownika.
Plusy:
Minusy: