Deconstrucción en C# 7.0

En nuestra entrega anterior, dedicada a las tuplas-valor (value tuples) añadidas recientemente a C# 7.0, mencionamos brevemente el mecanismo de deconstrucción (deconstruction), al que dedicaremos aquí algo más de espacio. La deconstrucción es un nuevo mecanismo sintáctico que aprovecha la sintaxis incorporada al lenguaje para representar tipos de tuplas-valor para permitir, de una manera sencilla y conveniente, descomponer un objeto de cualquier tipo en las partes que lo componen, asignando los valores de esas partes a nuevas variables (en cuyo caso estamos en presencia de una declaración de deconstrucción, deconstructing declaration) o a variables ya existentes (asignación de deconstrucción, deconstructing assignment):

    var dh = new Person("Denis"new DateTime(19851227));
    // ...
    (string name, int year, int month, int day) = dh;  // declaración
    string s;
    int y, m, d;
    (s, y, m, d) = dh;  // asignación
}

Como se habrá dado cuenta el lector, en el fondo se trata de simple azúcar sintáctico que evita tener que hacer uso de múltiples asignaciones y/o llamadas con incómodos parámetros out. Para satisfacer al compilador, es necesario que el tipo a descomponer ofrezca un método Deconstruct con los parámetros adecuados (en él es donde precisamente se encapsulan esos parámetros out). Deconstruct puede incluso ser un método extensor (extension method) que esté en ámbito, lo que hace posible utilizar el mecanismo para tipos de los cuales no disponemos del código fuente. Además, se puede implementar varias sobrecargas para ofrecer varias maneras de deconstruir un objeto. Por ejemplo, el código mostrado anteriormente funciona porque las siguientes definiciones están en vigor:

using System;
namespace ValueTuples
{
    public class Person
    {
        public string Name { get; }
        public DateTime BirthDate { get; }

        public Person(string name, DateTime birthDate)
        {
            Name = name;
            BirthDate = birthDate;
        }

        public void Deconstruct(out string name,
            out int year, out int month, out int day)
        {
            name = Name;
            BirthDate.Deconstruct(out year, out month, out day);
        }
    }

    public static class Extensions
    {
        public static void Deconstruct(this DateTime dateTime,
            out int year, out int month, out int day)
        {
            year  = dateTime.Year;
            month = dateTime.Month;
            day   = dateTime.Day;
        }
    }
}

Visto todo lo anterior, solo resta mencionar algunos detalles adicionales:

  • Las tuplas-valor soportan de manera predefinida la deconstrucción en sus componentes originales sin que tengamos que hacer absolutamente nada; veremos más detalles al respecto en una próxima entrega, que ya estaba prometida :-).
  • Los descartes, que ya presentamos hace algún tiempo, pueden ser útiles en caso de que solo estemos interesados en algunos de los elementos resultantes de la deconstrucción, como se muestra en el siguiente ejemplo:
using System;
namespace ValueTuples
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var dh = new Person("Denis"new DateTime(19851227));
            // ...
            (string name, int year, _, _) = dh;
            Console.WriteLine($"Name: {name}");
            Console.WriteLine($"Year: {year}");
        }
    }
}

Es precisamente esta aplicación conjunta de la deconstrucción y los descartes lo que tanto me recuerda al lenguaje de programación lógica Prolog. Aunque hay que reconocer que, incluso con todas las novedades añadidas a C# 7.0 y 7.1, C# aún se queda bastante corto: la unificación de Prolog es bidireccional, y las variables (y los descartes) pueden situarse a cualquiera de los dos lados del símbolo de unificación (que no asignación); más aún, el mecanismo de unificación de Prolog se basa en un algoritmo de emparejamiento de patrones (pattern matching) mucho más general, y que no depende para su funcionamiento de que se definan de antemano métodos especializados o se restrinjan en modo alguno las estructuras de las tuplas a unificar.


Agradecimientos: Lo poco que sé sobre Programación Lógica y sus aplicaciones lo aprendí de un MAESTRO con mayúsculas, Don Luciano García Garrido, a quien envío desde aquí un afectuoso saludo.

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 *