Cómo realizar la inicialización diferida en C #

La inicialización diferida es una técnica que pospone la creación de un objeto hasta la primera vez que se necesita. En otras palabras, la inicialización del objeto ocurre solo bajo demanda. Tenga en cuenta que los términos inicialización diferida e instanciación diferida significan lo mismo: se pueden utilizar indistintamente. Aprovechando la inicialización diferida, puede mejorar el rendimiento de la aplicación evitando cálculos innecesarios y consumo de memoria. En este artículo veremos cómo podemos realizar la inicialización diferida en C #.

Entendamos la carga diferida con un ejemplo simple. Considere dos clases Customery Order. La Customerclase contiene una Orderspropiedad que, a su vez, hace referencia a una colección de instancias de la Orderclase. La Orderscolección puede contener una gran cantidad de datos e incluso puede necesitar una conexión a la base de datos para conectarse a la base de datos y recuperar registros. En tal caso, no tiene sentido cargar datos en la Orderspropiedad hasta que los necesitemos. La inicialización diferida nos permite cargar la Orderscolección solo cuando se solicitan los datos.

Usando la clase Lazy en C #

Aunque puede escribir su propio código personalizado para implementar la inicialización diferida, Microsoft recomienda usar la Lazyclase en su lugar. La Lazyclase en el Systemespacio de nombres en C # se introdujo como parte de .Net Framework 4.0 para proporcionar una forma segura de implementar la inicialización diferida. Puede aprovechar esta clase para aplazar la inicialización de objetos que consumen muchos recursos en su aplicación.

Cuando usa la Lazyclase, debe especificar el tipo de objeto que desea crear de manera perezosa en el argumento de tipo. Tenga en cuenta que la inicialización diferida se produce cuando accede a la Lazy.Valuepropiedad. A continuación, se muestra un ejemplo de cómo Lazyse puede utilizar la clase:

Perezoso
   
     pedidos = nuevo Lazy
    
     ();
     

IEnumerable result = lazyOrders.Value;

Ahora, considere dos clases Authory Blog. Un autor puede escribir muchas publicaciones de blog, por lo que tiene una relación de uno a muchos entre las clases Authory Blogcomo se muestra en el fragmento de código a continuación.

Autor de clase pública

    {

        public int Id {obtener; conjunto; }

        cadena pública FirstName {get; conjunto; }

        cadena pública LastName {get; conjunto; }

        Dirección de cadena pública {get; conjunto; }

        Lista de blogs públicos {get; conjunto; }

    }

    Blog de clase pública

    {

        public int Id {obtener; conjunto; }

        Título de cadena pública {get; conjunto; }

        public DateTime PublicationDate {get; conjunto; }

    }

Tenga en cuenta que la relación de uno a varios entre las clases Authory Blogse ha representado mediante una Listpropiedad (de tipo Blog) en la Authorclase. Con esta propiedad, la Authorclase puede contener una colección de una o más instancias de la Blogclase.

Ahora suponga que necesitamos mostrar solo los detalles de un autor (nombre, apellido y dirección) en la interfaz de usuario. No tiene sentido cargar los detalles del blog para el autor en este caso; queremos cargar los detalles del blog con pereza. Aquí está la Authorclase actualizada que aborda esta necesidad. Tenga en cuenta el uso de la Lazyclase.

Autor de clase pública

    {

        public int Id {obtener; conjunto; }

        cadena pública FirstName {get; conjunto; }

        cadena pública LastName {get; conjunto; }

        Dirección de cadena pública {get; conjunto; }

        público perezoso Blogs => nuevo Lazy (() => GetBlogDetailsForAuthor (this.Id));

        IList privado GetBlogDetailsForAuthor (int Id)

        {

       // Escriba el código aquí para recuperar todos los detalles del blog de un autor.

        }

    }

Usando la clase Lazy genérica en C #

Veamos ahora cómo podemos aprovechar una Lazyclase genérica para implementar el patrón de diseño Singleton. (Puede leer mi artículo sobre el patrón de diseño Singleton aquí). La siguiente versión de la StateManagerclase es segura para subprocesos. Al mismo tiempo, demuestra una inicialización diferida. Tenga en cuenta que el constructor estático explícito se ha utilizado para garantizar que el compilador de C # no marque el tipo como beforefieldinit.

StateManager clase pública sellada

    {

        StateManager privado ()

        {

        }

        Instancia pública de StateManager estática

        {

            obtener

            {

                return Nested.obj;

            }

        }

        clase privada anidada

        {

            estático anidado ()

            {

            }

            StateManager estático interno de solo lectura obj = new StateManager ();

        }

    }

Aquí hay una implementación perezosa de la StateManagerclase que aprovecha la Lazyclase. Puedes ver cómo la Lazyclase hace que sea realmente sencillo implementar la pereza. 

StateManager clase pública

    {

        privado estático de solo lectura Lazy obj = new Lazy (() => new StateManager ());

        StateManager privado () {}

        Instancia pública de StateManager estática

        {

            obtener

            {

                return obj.Value;

            }

        }

    }

Eche un vistazo a la Instancepropiedad en la StateManagerclase anterior. Tenga en cuenta que la Valuepropiedad que ve en el ejemplo de código anterior es de solo lectura. Por esa razón, no hay un descriptor de acceso establecido.

La inicialización diferida es una excelente técnica de optimización del rendimiento que le permite diferir la inicialización de objetos que consumen una cantidad significativa de recursos de CPU y memoria hasta que los necesite absolutamente. Aproveche la inicialización diferida para mejorar el rendimiento de sus aplicaciones.