C# 8.0: Declaraciones using

“Make everything as simple as possible, but not simpler”
Albert Einstein

Finalmente he logrado sacar un rato libre para empezar a probar la preview de C# 8.0 (versión que vendrá atada a .NET Core 3.0, como se preveía) y evaluar de manera práctica las nuevas incorporaciones que presenta. Y para empezar por las novedades más sencillas, este artículo se centra en las declaraciones using (using declarations), que simplifican el código y facilitan su lectura al mismo tiempo que nos ahorran unos cuantos paréntesis y llaves.

En esencia, un código como el siguiente:

{
    // ...
    using (var file = new System.IO.StreamWriter(filePath))
    {
        foreach (string line in lines)
            file.WriteLine(line);
    } // aquí se dispone de 'file'
    // *** otras sentencias
}

ahora podrá simplificarse de esta manera:

{
    // ...
    using var file = new System.IO.StreamWriter(filePath);
    foreach (string line in lines)
        file.WriteLine(line);
    // *** otras sentencias
} // aquí se dispone de 'file' 

Tenga en cuenta que al usar la nueva sintaxis, la llamada automática a Dispose() para disponer del objeto referenciado por la variable definida (en este caso file) se produce al final del bloque (ámbito) de su declaración, por lo que en el fragmento anterior el objeto seguiría “vivo” durante la ejecución de “otras sentencias“, a diferencia de lo que ocurriría si se utilizara la sintaxis mostrada inicialmente. Pero probablemente el escenario más común sea aquél en que “otras sentencias” es un conjunto vacío (imagine, por ejemplo, que el bloque anterior fuera el cuerpo de un método que escribe un conjunto de líneas de texto a un fichero). Pienso que, en el caso general, la ganancia en legibilidad que produce la indentación simplificada es razón más que suficiente para dar preferencia a esta nueva sintaxis.

Revisando los artículos que se han escrito ya sobre las declaraciones using, encontré varios muy recomendables, en particular éste de @vcsjones, del que extraje este ejemplo simpático:

public static bool MightBeExe(string filePath)
{
    using var file = File.Open(filePath, FileMode.Open);
    var firstBytes = new byte[2];
    var bytesRead = file.Read(firstBytes, 0, 2);
    return bytesRead == 2 && 
        firstBytes[0] == (byte)'M' && firstBytes[1] == (byte)'Z';
}

Este método determina si un fichero específico pudiera ser un ejecutable (aunque no llevara la extensión .EXE), basándose en algo que es como un monumento a la vanidad humana: el formato de los ficheros ejecutables de DOS y Windows comienza con “MZ” porque así lo quiso el arquitecto de Microsoft que los diseñó, Mark Zbikowski.

El hecho de que en este método detrás de “using var” aparezcan dos declaraciones var me hizo pensar en lo siguiente: ¿y no será que using es realmente innecesario, y que podríamos dejar a un compilador inteligente la tarea de determinar si cualquier objeto instanciado localmente implementa IDisposable, para disponer de él automáticamente al final del bloque? Parece que los miembros del equipo de C# pensaron también en eso, y decidieron no llegar a tales extremos por las complicaciones potenciales en relación con la propiedad (ownership) de los objetos. Simplificar, sí, pero no más de lo necesario – es lo que parecen haber pensado. Este hilo de reddit contiene bastante información al respecto.


Referencia cultural: Sin duda uno de los cerebros más brillantes que ha dado la humanidad, Albert Einstein no solo nos dejó su Teoría de la Relatividad, sino también una buena cantidad de citas interesantes.

Octavio Hernandez

Desarrollador y consultor en tecnologías .NET. Microsoft C# MVP entre 2004 y 2010.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *