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 Customer
y Order
. La Customer
clase contiene una Orders
propiedad que, a su vez, hace referencia a una colección de instancias de la Order
clase. La Orders
colecció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 Orders
propiedad hasta que los necesitemos. La inicialización diferida nos permite cargar la Orders
colecció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 Lazy
clase en su lugar. La Lazy
clase en el System
espacio 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 Lazy
clase, 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.Value
propiedad. A continuación, se muestra un ejemplo de cómo Lazy
se puede utilizar la clase:
Perezosopedidos = nuevo Lazy (); IEnumerable result = lazyOrders.Value;
Ahora, considere dos clases Author
y Blog
. Un autor puede escribir muchas publicaciones de blog, por lo que tiene una relación de uno a muchos entre las clases Author
y Blog
como 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 Author
y Blog
se ha representado mediante una List
propiedad (de tipo Blog
) en la Author
clase. Con esta propiedad, la Author
clase puede contener una colección de una o más instancias de la Blog
clase.
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 Author
clase actualizada que aborda esta necesidad. Tenga en cuenta el uso de la Lazy
clase.
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 Lazy
clase 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 StateManager
clase 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 StateManager
clase que aprovecha la Lazy
clase. Puedes ver cómo la Lazy
clase 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 Instance
propiedad en la StateManager
clase anterior. Tenga en cuenta que la Value
propiedad 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.