Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Una instancia de una clase, un objeto, se crea mediante la New
palabra clave . Las tareas de inicialización a menudo deben realizarse en nuevos objetos antes de que se usen. Entre las tareas comunes de inicialización se incluyen abrir archivos, conectarse a bases de datos y leer valores de claves del Registro. Visual Basic controla la inicialización de nuevos objetos mediante procedimientos denominados constructores (métodos especiales que permiten el control sobre la inicialización).
Una vez que un objeto deja el ámbito, common Language Runtime (CLR) lo libera. Visual Basic controla la liberación de los recursos del sistema mediante procedimientos denominados destructores. Juntos, los constructores y los destructores permiten la creación de bibliotecas de clases completas y predecibles.
Usar constructores y destructores
Los constructores y destructores controlan la creación y destrucción de objetos. Los Sub New
procedimientos y Sub Finalize
de Visual Basic inicializan y destruyen objetos; reemplazan los Class_Initialize
métodos y Class_Terminate
usados en Visual Basic 6.0 y versiones anteriores.
Sub New
El Sub New
constructor solo se puede ejecutar una vez cuando se crea una clase. No se puede llamar explícitamente en ningún lugar que no sea la primera línea de código de otro constructor de la misma clase o de una clase derivada. Además, el código del Sub New
método siempre se ejecuta antes de cualquier otro código de una clase. Visual Basic crea implícitamente un Sub New
constructor en tiempo de ejecución si no define explícitamente un Sub New
procedimiento para una clase.
Para crear un constructor para una clase, cree un procedimiento denominado Sub New
en cualquier parte de la definición de clase. Para crear un constructor con parámetros, especifique los nombres y los tipos de datos de los argumentos en Sub New
de la misma manera que especificaría los argumentos para cualquier otro procedimiento, como en el código siguiente:
Sub New(ByVal s As String)
Los constructores suelen sobrecargarse con frecuencia, como en el código siguiente:
Sub New(ByVal s As String, i As Integer)
Cuando se define una clase derivada de otra clase, la primera línea de un constructor debe ser una llamada al constructor de la clase base, a menos que la clase base tenga un constructor accesible que no tome parámetros. Una llamada a la clase base que contiene el constructor anterior, por ejemplo, sería MyBase.New(s)
. De lo contrario, MyBase.New
es opcional y el entorno de ejecución de Visual Basic lo llama implícitamente.
Después de escribir el código para llamar al constructor del objeto primario, puede agregar cualquier código de inicialización adicional al Sub New
procedimiento.
Sub New
puede aceptar argumentos cuando se llama como un constructor con parámetros. Estos parámetros se pasan desde el procedimiento que llama al constructor, por ejemplo, Dim AnObject As New ThisClass(X)
.
Sub finalizar
Antes de liberar objetos, CLR llama automáticamente al Finalize
método para los objetos que definen un Sub Finalize
procedimiento. El Finalize
método puede contener código que necesita ejecutarse justo antes de que se destruya un objeto, como código para cerrar archivos y guardar información de estado. Hay una ligera penalización de rendimiento para ejecutar Sub Finalize
, por lo que debe definir un Sub Finalize
método solo cuando necesite liberar objetos explícitamente.
Nota:
El recolector de elementos no utilizados de CLR no elimina (y no puede) objetos no administrados, objetos que el sistema operativo ejecuta directamente, fuera del entorno CLR. Esto se debe a que los distintos objetos no administrados deben eliminarse de maneras diferentes. Esa información no está asociada directamente con el objeto no administrado; debe encontrarse en la documentación del objeto . Una clase que usa objetos no administrados debe eliminarlos en su Finalize
método .
El Finalize
destructor es un método protegido al que solo se puede llamar desde la clase a la que pertenece o desde clases derivadas. El sistema llama Finalize
automáticamente cuando se destruye un objeto, por lo que no debe llamar Finalize
explícitamente desde fuera de la implementación de Finalize
una clase derivada.
A diferencia de Class_Terminate
, que se ejecuta en cuanto un objeto se establece en Nothing, suele haber un retraso entre el momento en que un objeto pierde su ámbito y el momento en que Visual Basic llama al destructor Finalize
. Visual Basic .NET permite un segundo tipo de destructor, , IDisposable.Disposeque se puede llamar explícitamente en cualquier momento para liberar inmediatamente los recursos.
Nota:
Un Finalize
destructor no debe iniciar excepciones, ya que la aplicación no puede controlarla y puede hacer que la aplicación finalice.
Cómo funcionan los métodos New y Finalize en una jerarquía de clases
Cada vez que se crea una instancia de una clase, Common Language Runtime (CLR) intenta ejecutar un procedimiento denominado New
, si existe en ese objeto.
New
es un tipo de procedimiento denominado que constructor
se usa para inicializar nuevos objetos antes de que se ejecute cualquier otro código de un objeto. Un New
constructor se puede usar para abrir archivos, conectarse a bases de datos, inicializar variables y ocuparse de cualquier otra tarea que sea necesario realizar antes de que se pueda usar un objeto.
Cuando se crea una instancia de una clase derivada, el Sub New
constructor de la clase base se ejecuta primero, seguido de constructores en clases derivadas. Esto sucede porque la primera línea de código de un Sub New
constructor usa la sintaxis MyBase.New()
para llamar al constructor de la clase inmediatamente encima de sí misma en la jerarquía de clases. A continuación, se llama al constructor Sub New
para cada clase de la jerarquía de clases hasta que se alcanza el constructor de la clase base. En ese momento, el código del constructor de la clase base se ejecuta, seguido del código de cada constructor de todas las clases derivadas y el código de la mayoría de las clases derivadas se ejecuta en último lugar.
Cuando ya no se necesita un objeto, el método Finalize es llamado por el CLR antes de liberar su memoria. El método Finalize se llama destructor
porque realiza tareas de limpieza, como guardar información de estado, cerrar archivos y conexiones a bases de datos, y otras tareas que deben realizarse antes de liberar el objeto.
Interfaz IDisposable
Las instancias de clase suelen controlar los recursos no administrados por el CLR, como los identificadores de Windows y las conexiones de base de datos. Estos recursos se deben desechar en el Finalize
método de la clase, de modo que se liberarán cuando el recolector de basura destruya el objeto. Sin embargo, el recolector de basura destruye los objetos solo cuando el CLR requiere más memoria libre. Esto significa que es posible que los recursos no se liberen hasta mucho tiempo después de que el objeto salga del ámbito.
Para complementar la recolección de basura, tus clases pueden proporcionar un mecanismo para gestionar activamente los recursos del sistema si implementan la interfaz IDisposable.
IDisposable tiene un método, Dispose, al que los clientes deben llamar cuando terminen de usar un objeto . Puede usar el Dispose método para liberar inmediatamente los recursos y realizar tareas como cerrar archivos y conexiones de base de datos. A diferencia del Finalize
destructor, el método Dispose no se llama automáticamente. Los clientes de una clase deben llamar a Dispose explícitamente cuando quieran liberar los recursos de inmediato.
Implementación de IDisposable
Una clase que implemente la IDisposable interfaz debe incluir estas secciones de código:
Campo para realizar un seguimiento de si el objeto se ha eliminado:
Protected disposed As Boolean = False
Una sobrecarga de Dispose que libere los recursos de la clase. Los métodos Dispose y
Finalize
de la clase base deben llamar a este método.Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Insert code to free managed resources. End If ' Insert code to free unmanaged resources. End If Me.disposed = True End Sub
Una implementación de Dispose que contiene solo el código siguiente:
Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub
Invalidación del
Finalize
método que contiene solo el código siguiente:Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub
Derivación de una clase que implementa IDisposable
Una clase que deriva de una clase base que implementa la IDisposable interfaz no necesita invalidar ninguno de los métodos base, a menos que use recursos adicionales que deban eliminarse. En esa situación, la clase derivada debe invalidar el método de Dispose(disposing)
la clase base para eliminar los recursos de la clase derivada. Este reemplazo debe llamar al método Dispose(disposing)
de la clase base.
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposed Then
If disposing Then
' Insert code to free managed resources.
End If
' Insert code to free unmanaged resources.
End If
MyBase.Dispose(disposing)
End Sub
Una clase derivada no debe sobrescribir los métodos Dispose y Finalize
de la clase base. Cuando se llama a dichos métodos desde una instancia de la clase derivada, la implementación de la clase base de los métodos llama al reemplazo de la clase derivada del método Dispose(disposing)
.
Recolección de elementos no utilizados y el destructor Finalize
.NET Framework usa el sistema de recolección de elementos no utilizados con seguimiento de referencias para liberar periódicamente los recursos no usados. Visual Basic 6.0 y versiones anteriores usaron un sistema diferente denominado recuento de referencias para administrar los recursos. Aunque ambos sistemas realizan la misma función automáticamente, hay algunas diferencias importantes.
CLR destruye periódicamente los objetos cuando el sistema determina que estos objetos ya no son necesarios. Los objetos se liberan más rápidamente cuando los recursos del sistema están escasos, y con menos frecuencia de lo contrario. El retraso entre cuando un objeto pierde ámbito y cuando CLR libera significa que, a diferencia de los objetos de Visual Basic 6.0 y versiones anteriores, no puede determinar exactamente cuándo se destruirá el objeto. En tal situación, se dice que los objetos tienen una duración no determinista. En la mayoría de los casos, el ciclo de vida no determinista no cambia la forma en que se escriben las aplicaciones, siempre que recuerde que el destructor Finalize
puede no ejecutarse inmediatamente cuando un objeto sale del ámbito.
Otra diferencia entre los sistemas de recolección de basura implica el uso de Nothing
. Para aprovechar el recuento de referencias en Visual Basic 6.0 y versiones anteriores, los programadores a veces asignaban Nothing
a variables de objeto para liberar las referencias que esas variables mantenían. Si la variable mantuvo la última referencia al objeto, los recursos del objeto se liberaron inmediatamente. En versiones posteriores de Visual Basic, aunque puede haber casos en los que este procedimiento sigue siendo valioso, realizarlo nunca hace que el objeto al que se hace referencia libere sus recursos inmediatamente. Para liberar recursos inmediatamente, use el método del Dispose objeto, si está disponible. El único caso en el que una variable debe establecerse en Nothing
es cuando su duración sea larga en comparación con el tiempo que tarda el recolector de elementos no utilizados en detectar objetos huérfanos.