Natknąłem się na tę odpowiedź na StackOverflow pewnego dnia i chciałem zwrócić na nią uwagę (podkreślenie moje):
Miałem ten problem podczas debugowania, gdy miałem zegarek, który próbował zwrócić element „brakującego” klucza . W rzeczywistości dalsze sfrustrowane debugowanie miało ten sam problem, gdy dosłownie obserwowałem [scriptingdictonaryObject].exists() warunkowy); Proponuję dodanie „brakującego” klucza ze względu na zegarek . Kiedy usunąłem zegarek i zamiast tego utworzyłem tymczasowy arkusz roboczy do kopiowania tablicy podczas działania, niechciane klucze nie były już dodawane.Obiekt słownika dodający elementy przed wywołaniem .add() Używam obiektu słownika z biblioteki MS Scripting Runtime do przechowywania serii tablic i wykonywania operacji na komórkach tablicy w razie potrzeby. Istnieje pętla for, która przechodzi przez ten proces... Przepełnienie stosuriddley_w
Co tu się dzieje?
Jedną z „cech” obiektu Dictionary jest to, że niejawnie tworzyć nowe elementy bez konieczności wywoływania metody .Add jawnie . Jaka jest różnica między niejawną a jawną?
Uwaga:wczesne użycie obiektu Dictionary wymaga odwołania do „Microsoft Scripting Runtime” (szczegóły tutaj).
Dim MyDict As New Dictionary
'Explicit add
MyDict.Add "KeyA", "Item A"
'Implicit add
MyDict.Item("KeyB") = "Item B"
Debug.Print MyDict("KeyA"); vbNewLine; MyDict("KeyB")
Oto odpowiednia część dokumentacji dotyczącej niejawnej tworzenie kluczy:
Uwagi
Jeśli klucz nie można znaleźć podczas zmiany elementu , nowy klucz jest tworzony z określonym newtem . Jeśli klucz nie zostanie znaleziony podczas próby zwrócenia istniejącego elementu, nowy klucz jest tworzony, a odpowiadający mu element pozostaje pusty.
Odtwarzanie problemu
Odtwórzmy problem, aby zobaczyć, gdzie dokładnie wszystko idzie na boki.
Oczekiwane zachowanie
Utwórz następującą przykładową procedurę:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Uruchom powyższą procedurę z bezpośredniego okna i powinna ona zwrócić False:
WatchOut
KeyA exists? False
Dodaj zegarek
Teraz dodajmy zegarek z pozycji „KeyA”:
Spróbujmy uruchomić WatchOut znowu rutyna:
WatchOut
KeyA exists? False
Jak na razie dobrze. Może to wcale nie jest problem.
Przejdź przez kod
Dodajmy Stop oświadczenie, aby wymusić złamanie kodu:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Stop
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Teraz spróbujmy uruchomić WatchOut rutyna:
WatchOut
KeyA exists? True
Aha! Wystarczy połączenie zegarka i włamania do debuggera, aby wymusić pojawienie się „błędu”. Wstawiłem błąd w przerażających cudzysłowach, ponieważ jest to właściwie oczekiwane zachowanie debugera. Ale prawie na pewno jest to nieoczekiwane zachowanie dewelopera.
(Pamiętaj, że nie ma nic szczególnego w Zatrzymaniu polecenie, które powoduje to zachowanie. Możesz usunąć Zatrzymaj i ustaw punkt przerwania w kodzie, a wystąpi to samo zachowanie.)
Możesz zobaczyć, gdzie tego rodzaju rzeczy mogą spowodować, że podczas debugowania będziesz wyrywać sobie włosy. Za każdym razem, gdy zachowanie twojego programu jest inne podczas normalnego działania i podczas debugowania, masz zadatki na jedną pogarszającą się sesję debugowania.
Podsumowanie
Kroki prowadzące do odtworzenia problemu:
- Utwórz zegarek dla określonego elementu słownika
- Włam się do debugera podczas wykonywania kodu
To prawdopodobnie pomoże tylko jednemu lub dwóm programistom. Ale potencjalnie zaoszczędzi to programistom godzin frustracji. I jeśli mam być szczery, jak każdy, jestem jednym z tych programistów;-).