sql >> Base de Datos >  >> RDS >> Access

Cuidado con lo que miras

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:

  1. Crear un reloj para un elemento específico del diccionario
  2. 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;-).