Encontré esta respuesta en StackOverflow el otro día y quería llamar la atención (el énfasis es mío):
Este problema se manifestó durante la depuración cuando tenía un reloj que intentaba devolver el elemento de la llave "faltante" . En realidad, la depuración más frustrada tuvo el mismo problema cuando, literalmente, observé el [scriptingdictonaryObject].exists() condicional); Sugiero que la clave "faltante" se agregue debido al reloj . Cuando eliminé el reloj y en su lugar creé una hoja de trabajo temporal para copiar la matriz mientras se ejecutaba, las claves no deseadas ya no se agregaron.Objeto de diccionario que agrega elementos antes de llamar a .add() Estoy usando un objeto de diccionario de la biblioteca MS Scripting Runtime para almacenar una serie de matrices y realizar operaciones en las celdas de la matriz según sea necesario. Hay un bucle for para pasar por el proceso... Desbordamiento de pilariddley_w
¿Qué está pasando aquí?
Una de las "características" de un objeto Dictionary es que implícitamente crear nuevos elementos sin necesidad de llamar al método .Add explícitamente . ¿Cuál es la diferencia entre implícito y explícito?
Nota:el uso de enlace anticipado del objeto Dictionary requiere una referencia al "Microsoft Scripting Runtime" (detalles aquí).
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")
Aquí está la parte relevante de la documentación con respecto a implícito creación de clave:
Comentarios
Si clave no se encuentra al cambiar un elemento , una nueva clave se crea con el nuevo elemento especificado . Si clave no se encuentra al intentar devolver un artículo existente, una nueva clave se crea y su elemento correspondiente se deja vacío.
Reproduciendo el problema
Reproduzcamos el problema para ver exactamente dónde van las cosas.
Comportamiento esperado
Cree la siguiente rutina de ejemplo:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Ejecute la rutina anterior desde la ventana inmediata y debería devolver False:
WatchOut
KeyA exists? False
Agregar un reloj
Ahora, agreguemos un reloj del elemento "KeyA":
Intentemos ejecutar WatchOut rutina de nuevo:
WatchOut
KeyA exists? False
Hasta aquí todo bien. Quizás esto no sea un problema después de todo.
Paso a paso por el código
Agreguemos una Parada instrucción para forzar la ruptura del código:
Sub WatchOut()
Dim MyDict As Dictionary
Set MyDict = New Dictionary
Stop
Debug.Print "KeyA exists? "; MyDict.Exists("KeyA")
End Sub
Ahora, intentemos ejecutar WatchOut rutina:
WatchOut
KeyA exists? True
¡Ajá! La combinación del reloj y la irrupción en el depurador es suficiente para forzar la aparición del "error". Puse bicho entre comillas porque en realidad es el comportamiento esperado para el depurador. Pero es casi seguro que se trata de un comportamiento inesperado para el desarrollador.
(Tenga en cuenta que no hay nada especial en Stop comando que causa este comportamiento. Puede eliminar la Parada y establezca un punto de interrupción en el código y se producirá el mismo comportamiento).
Puede ver dónde este tipo de cosas podría hacer que se tire de los pelos durante la depuración. Cada vez que el comportamiento de su programa es diferente mientras se ejecuta normalmente en comparación con la depuración, tiene las características de una sesión de depuración agravante.
Resumen
Pasos para reproducir el problema:
- Crear un reloj para un elemento específico del diccionario
- Irrumpir en el depurador mientras se ejecuta el código
Esto probablemente solo ayudará a uno o dos desarrolladores. Pero potencialmente ahorrará a esos desarrolladores horas de frustración Y, si te soy sincero, tengo tantas probabilidades como cualquiera de ser uno de esos desarrolladores;-).