¿Hay alguna necesidad de establecer objetos a nada dentro de las funciones de VBA?

Siempre leo que se recomienda dejar los objetos en cero una vez que haya terminado con ellos. Pero normalmente los uso solo en funciones dentro de formularios.

¿No se pierde la referencia y se libera la memoria cuando queda el scope de la función, independientemente de establecer objetos en Nothing?

es decir, es realmente necesario hacer:

Set db = Nothing Set record_set = Nothing 

VB usa un recolector de basura llamado “conteo de referencia”.

Básicamente, en el momento en que una variable sale del scope, el contador de referencia en el objeto al que se hace referencia se reduce. Cuando asigna la referencia del objeto a otra variable, el contador de referencia se incrementa.

Cuando el contador llega a cero, el objeto está listo para la recolección de basura. Los recursos del objeto se liberarán tan pronto como esto suceda. Una variable local de función muy probablemente hará referencia a un objeto cuyo recuento de referencias nunca va más allá de 1, por lo que los recursos del objeto se liberarán cuando la función finalice.

Establecer una variable a Nothing es la forma de disminuir el contador de referencia explícitamente.

Por ejemplo, lee en un archivo y establece la variable de objeto de archivo en Nothing justo después de la llamada a ReadAll() . El identificador de archivo se lanzará inmediatamente, puede tomar su tiempo procesar sus contenidos.

Si no establece Nothing , el manejador de archivo puede abrirse más de lo necesario.

Si no se encuentra en el tipo de situación de “debe desbloquear recursos valiosos”, simplemente está permitido dejar las variables fuera del scope.

La recolección de basura rara vez es perfecta. Incluso en .NET hay momentos en los que se recomienda encarecidamente que solicite al sistema que realice la recolección de basura con anticipación.

Por este motivo, explícitamente cierro y configuro nada en los conjuntos de registros cuando termino con ellos.

La última línea del tema de ayuda para ” Recordset.Close ” en la ayuda de Microsoft DAO y la Referencia de desarrollador de Access es esto:

“Una alternativa al método Close es establecer el valor de una variable de objeto en Nothing (Establecer dbsTemp = Nothing)”.

http://msdn.microsoft.com/en-us/library/bb243098.aspx

Con esto en mente, este artículo de Microsoft Knowledge Base titulado “Cómo evitar la saturación de la base de datos después de usar Objetos de acceso a datos (DAO)”, le dice que debe cerrar explícitamente si no desea que las bases de datos se llenen. Notarás que el artículo es un poco vago sobre los detalles; la sección “Causa” no está clara, casi hasta el punto de ser un galimatías.

http://support.microsoft.com/kb/289562

Síntomas: una base de datos de Microsoft Access ha comenzado a hincharse (o crecer rápidamente en tamaño) después de implementar objetos de acceso a datos (DAO) para abrir un conjunto de registros.

CAUSA: si no libera la memoria de un juego de registros cada vez que recorre el código del juego de registros, DAO puede volver a comstackr, utilizando más memoria y aumentando el tamaño de la base de datos.

MÁS INFORMACIÓN: cuando crea un objeto Recordset (o un QueryDef) en el código, cierre explícitamente el objeto cuando haya terminado. Microsoft Access cierra automáticamente los objetos Recordset y QueryDef en la mayoría de los casos. Sin embargo, si cierra de manera explícita el objeto en su código, puede evitar instancias ocasionales cuando el objeto permanece abierto.

Finalmente, permítanme agregar que he estado trabajando con bases de datos de Access durante 15 años, y casi siempre dejo que mis variables de conjunto de registros declaradas localmente salgan del scope sin usar explícitamente el método Close. No he hecho ninguna prueba al respecto, pero parece que no importa.

Se supone que las referencias se limpian cuando la variable queda fuera del scope. Presumiblemente, esto ha mejorado con versiones posteriores del software, pero en un momento no fue confiable. Creo que sigue siendo una buena práctica establecer explícitamente variables para “Nada”.

Cuando está utilizando ASP clásico (scripting del lado del servidor), es importante configurar todos los objetos cuando haya terminado con ellos, ya que no se salgan de scope hasta que se cierre el servidor [virtual].

Por esta razón, todos los ejemplos de scripting de MS VB siempre mostraban objetos cerrados y configurados como nada. Para que los extractos de la secuencia de comandos se puedan usar en entornos como ASP clásico, donde los objetos no salieron del scope.

Rara vez hay otras situaciones en las que desee codificar procesos de larga ejecución en los que los objetos no salgan del scope y se quede sin memoria física si no libera objetos explícitamente.

Si te encuentras codificando ASP clásico o ejecutando procesos en scope global por algún otro motivo, entonces sí, debes liberar objetos explícitamente.

Siempre pongo esto al final de mis procedimientos, o llamo a un sub de “CloseRecordSet” si estoy usando los de nivel de módulo:

 Private Sub Rawr() On Error GoTo ErrorHandler 'Procedural Code Here. ExitPoint: 'Closes and Destroys RecordSet Objects. If Not Recset Is Nothing Then If Recset.State = 1 Then Recset.Close Conn.Close End If Set Recset = Nothing Set Conn = Nothing End If Exit Sub ErrorHandler: 'Error Handling / Reporting Here. Resume ExitPoint End Sub 

De esta manera, sin embargo, el procedimiento finaliza (ya sea normalmente o debido a un error) los objetos se limpian y los recursos son gratuitos.

Hacerlo de esa manera es bastante seguro, ya que puede simplemente insertarlo y solo hará lo necesario en relación con el cierre o la destrucción del conjunto de registros / objeto de conexión, en caso de que ya se haya cerrado (debido a un error de tiempo de ejecución o solo cerrarlo temprano como debería, esto solo se asegura).

Realmente no es demasiada molestia y siempre es mejor limpiar tus objetos cuando termines con ellos para liberar recursos de forma inmediata sin importar lo que ocurra en el progtwig.

Prueba esto

 If Not IsEmpty(vMyVariant) Then Erase vMyVariant vMyVariant = Empty End If