En el artículo, Codificación de nuevas instancias de objetos, escribí sobre las diversas formas en que Nuevo Se pueden crear instancias de objetos. El problema opuesto, la disposición de un objeto, es algo de lo que no tendrá que preocuparse en VB.NET con mucha frecuencia. .NET incluye una tecnología llamada Recolector de basura (GC) que generalmente se encarga de todo detrás de escena de forma silenciosa y eficiente. Pero ocasionalmente, generalmente cuando se utilizan secuencias de archivos, objetos sql u objetos gráficos (GDI +) (es decir, recursos no gestionados), es posible que deba controlar la eliminación de objetos en su propio código.
Primero, algunos antecedentes
Solo como un estafastructor (el Nuevo palabra clave) crea una nueva objeto, un Delawarestructor es un método que se llama cuando se destruye un objeto. Pero hay una trampa. Las personas que crearon .NET se dieron cuenta de que era una fórmula para errores si dos partes diferentes de código podían destruir un objeto. Por lo tanto, .NET GC está realmente en control y generalmente es el único código que puede destruir la instancia del objeto. El GC destruye un objeto cuando lo decide y no antes. Normalmente, después de que un objeto sale del alcance, es
liberado por el Common Language Runtime (CLR). El GC destruye se opone cuando el CLR necesita más memoria libre. Entonces, la conclusión es que no puedes predecir cuándo GC realmente destruirá el objeto.(Welllll... Es verdad casi todo el tiempo. Puedes llamar GC.Collect y forzar un ciclo de recolección de basura, pero las autoridades dicen universalmente que es un malo idea y totalmente innecesaria.)
Por ejemplo, si su código ha creado un Cliente objeto, puede parecer que este código lo destruirá nuevamente.
Cliente = nada
Pero no lo hace. (Establecer un objeto en Nothing se llama comúnmente, desreferenciación el objeto.) En realidad, solo significa que la variable ya no está asociada con un objeto. Algún tiempo después, el GC notará que el objeto está disponible para su destrucción.
Por cierto, para los objetos gestionados, nada de esto es realmente necesario. Aunque un objeto como un botón ofrecerá un método de eliminación, no es necesario usarlo y pocas personas lo hacen. Los componentes de Windows Forms, por ejemplo, se agregan a un objeto contenedor denominado componentes. Cuando cierra un formulario, su método Dispose se llama automáticamente. Por lo general, solo tiene que preocuparse por esto cuando usa objetos no administrados, e incluso entonces solo para optimizar su programa.
La forma recomendada de liberar cualquier recurso que pueda contener un objeto es llamar al Disponer método para el objeto (si hay uno disponible) y luego desreferenciar el objeto.
Cliente. Disponer() Cliente = nada
Debido a que GC destruirá un objeto huérfano, ya sea que establezca o no la variable del objeto en Nothing, no es realmente necesario.
Otra forma recomendada de asegurarse de que los objetos se destruyan cuando ya no se necesiten es colocar el código que usa un objeto en un Utilizando bloquear. Un bloque de Uso garantiza la eliminación de uno o más de esos recursos cuando su código haya terminado con ellos.
En la serie GDI +, el Utilizando El bloque se usa con bastante frecuencia para administrar esos molestos objetos gráficos. Por ejemplo ...
Usando myBrush como LinearGradientBrush _. = Nuevo LinearGradientBrush (_. Yo. Rectángulo de cliente, _. Color. Color azul. Rojo, _. LinearGradientMode. Horizontal) <... m c ...> Terminar de usar
myBrush se elimina automáticamente cuando se ejecuta el final del bloque.
El enfoque de GC para administrar la memoria es un gran cambio con respecto a la forma en que lo hizo VB6. Los objetos COM (utilizados por VB6) se destruyeron cuando un contador interno de referencias llegó a cero. Pero era demasiado fácil cometer un error, por lo que el contador interno estaba apagado. (Debido a que la memoria estaba atada y no estaba disponible para otros objetos cuando esto sucedió, esto se denominó "pérdida de memoria"). En cambio, GC realmente comprueba si algo hace referencia a un objeto y lo destruye cuando ya no hay más referencias El enfoque GC tiene una buena historia en lenguajes como Java y es una de las grandes mejoras en .NET.
En la página siguiente, examinamos la interfaz IDisposable... la interfaz que debe usar cuando necesite desechar objetos no administrados en su propio código.
Si codifica su propio objeto que usa recursos no administrados, debe usar el IDisposable interfaz para el objeto. Microsoft facilita esto al incluir un fragmento de código que crea el patrón adecuado para usted.
Haga clic aquí para mostrar la ilustración.
Haga clic en el botón Atrás en su navegador para volver
El código que se agrega se ve así (VB.NET 2008):
Clase ResourceClass. Implementa IDisposable. 'Para detectar llamadas redundantes. Privado dispuesto como booleano = falso. 'IDisposable. Sub Disposición sobrerrestable protegida (_. ByVal desechando como booleano) Si no soy yo, dispuesto entonces. Si se dispone entonces. 'Otro estado libre (objetos gestionados). Terminara si. 'Libera tu propio estado (objetos no gestionados). 'Establecer campos grandes en nulo. Terminara si. Me.disposed = Verdadero. End Sub. #Region "IDisposable Support" 'Este código agregado por Visual Basic a. 'implementar correctamente el patrón desechable. Public Sub Dispose () Implementa IDisposable. Disponer. 'No cambie este código. 'Ponga el código de limpieza. 'Desechar (ByVal desechando como booleano) arriba. Deseche (verdadero) GC.SuppressFinalize (Me) End Sub. Protected Overrides Sub Finalize () 'No cambie este código. 'Ponga el código de limpieza. 'Desechar (ByVal desechando como booleano) arriba. Deseche (falso) MyBase. Finalizar () Finalizar sub. # Región final. Clase final
Disponer es casi un patrón de diseño de desarrollador "forzado" en .NET. Realmente solo hay una forma correcta de hacerlo y esta es. Puede pensar que este código hace algo mágico. No lo hace.
Primera nota que la bandera interna dispuesto simplemente cortocircuita todo para que pueda llamar Eliminar (desechar) tan seguido como quieras.
El código ...
GC.SuppressFinalize (Me)
... hace que su código sea más eficiente al decirle al GC que el objeto ya ha sido eliminado (una operación "costosa" en términos de ciclos de ejecución) Finalizar está protegido porque GC lo llama automáticamente cuando se destruye un objeto. Nunca deberías llamar a Finalizar. El booleano disponer le dice al código si su código inició la eliminación del objeto (True) o si el GC lo hizo (como parte del Finalizar sub. Tenga en cuenta que el único código que utiliza el booleano disponer es:
Si se dispone entonces. 'Otro estado libre (objetos gestionados). Terminara si
Cuando desecha un objeto, todos sus recursos deben eliminarse. Cuando el CLR recolector de basura desecha un objeto, solo los recursos no administrados deben eliminarse porque el recolector de basura se encarga automáticamente de los recursos administrados.
La idea detrás de este fragmento de código es que agregue código para cuidar los objetos administrados y no administrados en las ubicaciones indicadas.
Cuando deriva una clase de un clase base que implementa IDisposable, no tiene que anular ninguno de los métodos base a menos que use otros recursos que también deben eliminarse. Si eso sucede, la clase derivada debe anular el método Dispose (disposición) de la clase base para disponer de los recursos de la clase derivada. Pero recuerde llamar al método Dispose (disposing) de la clase base.
Sub Disposición de anulaciones protegidas (eliminación de ByVal como booleano) Si no soy yo. Si se dispone entonces. 'Agregue su código a recursos gestionados gratuitos. Terminara si. 'Agregue su código para liberar recursos no administrados. Terminara si. MyBase Eliminar (desechar) End Sub
El tema puede ser un poco abrumador. ¡El propósito de la explicación aquí es "desmitificar" lo que realmente está sucediendo porque la mayoría de la información que puedes encontrar no te dice nada!