Administración de recursos: palabra clave use
En este tema se describen la palabra clave use
y la función using
, que pueden controlar la inicialización y la liberación de recursos.
Recursos
El término recurso se usa de más de una forma. Sí, los recursos pueden ser datos que usa una aplicación, como cadenas, gráficos y similares, pero en este contexto, recursos se refiere a recursos de software o sistema operativo, como contextos de dispositivos gráficos, identificadores de archivos, conexiones de red y base de datos, objetos de simultaneidad como identificadores de espera, etc. El uso de estos recursos por parte de las aplicaciones implica la adquisición del recurso desde el sistema operativo u otro proveedor de recursos, seguida de la posterior liberación del recurso al grupo para que se pueda proporcionar a otra aplicación. Los problemas se producen cuando las aplicaciones no liberan los recursos al grupo común.
Administrar recursos
Para administrar recursos de forma eficaz y responsable en una aplicación, debe liberar los recursos de forma rápida y predecible. .NET Framework ayuda a hacerlo con la interfaz System.IDisposable
. Un tipo que implementa System.IDisposable
tiene el método System.IDisposable.Dispose
, que libera correctamente los recursos. Las aplicaciones bien escritas garantizan que se llame rápidamente a System.IDisposable.Dispose
cuando ya no se necesite algún objeto que contiene un recurso limitado. Afortunadamente, la mayoría de los lenguajes .NET proporcionan compatibilidad para facilitar esta tarea, y F# no es ninguna excepción. Hay dos construcciones de lenguaje útiles que admiten el patrón de eliminación: el enlace use
y la función using
.
Enlace use
La palabra clave use
tiene un formato similar al del enlace let
:
use valor = expresión
Proporciona la misma funcionalidad que un enlace let
, pero agrega una llamada a Dispose
en el valor cuando este se sale del ámbito. Observe que el compilador inserta una comprobación null en el valor, de modo que, si el valor es null
, la llamada a Dispose
no se intenta.
En el ejemplo siguiente se muestra cómo cerrar un archivo automáticamente mediante la palabra clave use
.
open System.IO
let writetofile filename obj =
use file1 = File.CreateText(filename)
file1.WriteLine("{0}", obj.ToString() )
// file1.Dispose() is called implicitly here.
writetofile "abc.txt" "Humpty Dumpty sat on a wall."
Varias instancias de use
se disponen en el orden inverso en el que se declaran. Es decir, la primera use
será la última publicada.
Nota:
Puede usar use
en expresiones de cálculo, en cuyo caso se emplea una versión personalizada de la expresión use
. Para obtener más información, vea Secuencias, Expresiones asincrónicas, Expresiones de tareas y Expresiones de cálculo.
Función using
La función using
tiene el siguiente formato:
using
(expression1) function-or-lambda
En una expresión using
, expression1 crea el objeto que se debe eliminar. El resultado de expression1 (el objeto que se debe eliminar) se convierte en un argumento, value, para function-or-lambda, que es una función que espera un único argumento restante de un tipo que coincida con el valor generado por expression1 o una expresión lambda que espera un argumento de ese tipo. Al final de la ejecución de la función, el runtime llama a Dispose
y libera los recursos (a menos que el valor sea null
, en cuyo caso no se intenta llamar a Dispose).
En el ejemplo siguiente se muestra la expresión using
con una expresión lambda.
open System.IO
let writetofile2 filename obj =
using (System.IO.File.CreateText(filename)) ( fun file1 ->
file1.WriteLine("{0}", obj.ToString() )
)
writetofile2 "abc2.txt" "The quick sly fox jumps over the lazy brown dog."
En el ejemplo siguiente se muestra la expresión using
con una función.
let printToFile (file1 : System.IO.StreamWriter) =
file1.WriteLine("Test output");
using (System.IO.File.CreateText("test.txt")) printToFile
Observe que la función podría ser una función con algunos argumentos ya aplicados. El siguiente ejemplo de código muestra esto. Crea un archivo que contiene la cadena XYZ
.
let printToFile2 obj (file1 : System.IO.StreamWriter) =
file1.WriteLine(obj.ToString())
using (System.IO.File.CreateText("test.txt")) (printToFile2 "XYZ")
La función using
y el enlace use
son formas prácticamente equivalentes de lograr lo mismo. La palabra clave using
proporciona más control sobre cuándo se llama a Dispose
. Cuando se usa using
, se llama a Dispose
al final de la función o expresión lambda; cuando se usa la palabra clave use
, se llama a Dispose
al final del bloque de código contenedor. En general, debe preferir el uso de use
en lugar de la función using
.