programowanieProgramista Backend (VB.NET)

Jak w Visual Basic tworzy się i używa słownika z dowolnymi kluczami (Dictionary), jaka jest różnica między Dictionary a Hashtable oraz jakie są szczególności w pracy z brakującymi kluczami?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Historia pytania:

W VB.NET standardowym rozwiązaniem do asocjacyjnego przechowywania danych (klucz-wartość) stała się klasa Dictionary(Of TKey, TValue). W klasycznym VB6 częściej używano obiektu Scripting.Dictionary lub kolekcji Collection, a także typu Hashtable, który pojawił się w wczesnych wersjach .NET. Te struktury pozwalają na szybkie znajdowanie wartości na podstawie klucza i zastąpiły mniej typowo bezpieczne podejścia.

Problem

Niekonwencjonalna różnica między Dictionary a Hashtable — i możliwe błędy przy wyszukiwaniu z brakującym kluczem. Na przykład próba dostępu do klucza, którego nie ma, kończy się błędem w niektórych przypadkach i nie w innych. Różnice w typowej bezpieczeństwie i wydajności prowadzą do błędnego wyboru kolekcji.

Rozwiązanie

W nowoczesnych wersjach VB.NET najlepszą praktyką jest użycie Dictionary(Of TKey, TValue), gdzie TKey i TValue są ściśle typowane:

Dim dict As New Dictionary(Of String, Integer)() dict.Add("apple", 1) dict.Add("banana", 2) If dict.ContainsKey("banana") Then Console.WriteLine(dict("banana")) ' Wyświetli 2 End If ' Bezpieczne pobranie wartości Dim value As Integer If dict.TryGetValue("cherry", value) Then Console.WriteLine(value) Else Console.WriteLine("Brak takiego klucza!") End If

Kluczowe cechy:

  • Dictionary(Of TKey, TValue) działa szybciej, jest standardowo typowo bezpieczny, pozwala na dowolne klucze (jeśli poprawnie zaimplementowany GetHashCode/Equals).
  • Hashtable przyjmuje i zwraca Object, nie obsługuje typów generycznych, jest wolniejszy i mniej wygodny w nowoczesnym kodzie.
  • Dostęp do brakującego klucza przez słownik generuje wyjątek KeyNotFoundException. Używaj ContainsKey lub TryGetValue, aby uzyskać bezpieczny dostęp.

Pytania z podchwytliwością.

Czy można użyć Object jako klucza bez ograniczeń w Dictionary?

Formalnie tak, ale wymagana jest prawidłowa implementacja metod GetHashCode i Equals w klasie, która służy jako klucz. W przeciwnym razie możliwe są kolizje i błędy wyszukiwania.

Co się stanie, jeśli odwołasz się do nieistniejącego klucza przez dict("foo")?

Zostanie rzucony wyjątek KeyNotFoundException. Bez wstępnej weryfikacji klucza (przez ContainsKey lub TryGetValue) program zakończy działanie.

Czy Dictionary i Hashtable wspierają tę samą kolejność elementów?

Nie. Obie klasy nie gwarantują kolejności dodawania elementów. Aby zachować porządek, użyj SortedDictionary, OrderedDictionary lub innych struktur.

Typowe błędy i antypatrony

  • Dostęp do wartości słownika bez sprawdzania obecności klucza.
  • Używanie Hashtable w nowoczesnym kodzie bez pilnej potrzeby — brak typowego bezpieczeństwa.
  • Używanie obiektów z niestabilnymi kodami haszujący jako kluczy (np. obiekty zmienne).

Przykład z życia

Negatywny przypadek

Programista wybrał Hashtable do przechowywania dużych ilości danych użytkowników. Występowały trudno uchwytne błędy — ten sam klucz nie zawsze się zgadzał, w testach pojawiały się błędy Object.ReferenceEquals, wiązano niestabilny typ klucza.

Plusy:

  • Szybkie prototypowanie, minimalnie działające rozwiązanie.

Minusy:

  • Trudno debugować.
  • Kolekcja typów "Object" — trudno śledzić błędy typów.
  • Nie działa TryGetValue.

Pozytywny przypadek

Przeszliśmy na Dictionary(Of Guid, User): ścisła typizacja, wsparcie dla TryGetValue, wyeliminowano błędy kolizji. Wydajność wzrosła.

Plusy:

  • Przewidywalne zachowanie.
  • Brak błędów typów, mniej czasu na debugowanie.

Minusy:

  • Wymagana poprawna implementacja GetHashCode/Equals, jeśli używany jest niestandardowy typ klucza.