Ojo con la inicialización de propiedades usando expression bodied members - Code Variables
Code Variables Code Variables

Latest news

جاري التحميل ...

Ojo con la inicialización de propiedades usando expression bodied members

.NET CoreHace poco estaba revisando un proyecto y me topé con un problema derivado de un uso extraño de los expression bodied members, y creo que es interesante comentarlo porque, aunque probablemente la mayoría no os vayáis a encontrar con esto, seguro que puede venir bien a alguien que no tenga del todo claro cómo y cuándo se debe utilizar esta sintaxis.

Pero comencemos desde el principio...

Evolución de la inicialización de propiedades

Como sabemos, el siguiente código es la forma "tradicional" de definir una propiedad de sólo lectura con backing field, inicializada a un valor concreto:
public class Example
{
private int _theNumber = 42;
public int TheNumber
{
get
{
return _theNumber;
}
}
}
C# 3 introdujo las propiedades automáticas, que eliminaban la necesidad de definir explícitamente un backing field. Esto simplificaba algo el código, pero su inicialización debíamos implementarla en el constructor:
public class Example
{
public int TheNumber { get; }
public Example()
{
TheNumber = 42;
}
}
Afortunadamente, C# 6 introdujo la posibilidad de inicializar directamente propiedades automáticas junto a su declaración, lo que permitía obtener el mismo resultado escribiendo un código más compacto:
public class Example
{
public int TheNumber { get; } = 42;
}
Y al mismo tiempo, C# 6 introdujo los expression bodied members, que luego fueron extendidos en C# 7 para permitir una sintaxis aún más concisa en determinados escenarios. Usando esta característica, el código anterior podríamos dejarlo en:
public class Example
{
public int TheNumber => 42;
}

¿Y cuál es el problema?

Ciertamente esta forma de inicializar propiedades usando expression bodied members es muy cómoda y compacta, pero puede confundir un poco si no sabemos exactamente qué estamos haciendo.

Imaginemos ahora el siguiente código, donde se utiliza => con el objetivo de inicializar una propiedad:
public class Example: IDisposable
{
public DatabaseConnection Connection => Database.OpenConnection(); // Mal!
public void AddOneHundredCustomers()
{
for(var i=1; i <= 100; i++)
{
Connection.AddCustomer(new Customer() { Id = i })
}
}
public void Dispose()
{
Connection.Dispose();
}
}
Aunque la intención en el uso de => era inicializar la propiedad, en realidad lo que estamos haciendo es instanciar un objeto DatabaseConnection cada vez que se accede a la propiedad Connection, tanto en el cuerpo de AddOneHundredCustomers() como en Dispose(). Es decir, durante la ejecución del siguiente código instanciaríamos 101 conexiones, y liberaríamos sólo la última de ellas:
using (var example = new Example())
{
example.AddOneHundredCustomers();
}
Lo importante aquí es entender que al usar esa sintaxis no estamos inicializando nada, sino indicando la expresión que retornará el valor de la propiedad cada vez que accedamos a ella.

Entonces, ¿cuál sería la forma correcta de hacerlo?

Pues como siempre ;) Por una parte declaramos la propiedad y luego la inicializamos en el constructor de la clase, o bien utilizamos los inicializadores de propiedades, como en el siguiente ejemplo:
public class Example : IDisposable
{
public DatabaseConnection Connection { get; } = Database.OpenConnection(); // Ok
...
}
En conclusión, cuando se introducen novedades al lenguaje, a los desarrolladores nos encanta comenzar a utilizarlas enseguida, a veces sin llegar a entender bien qué es lo que estamos haciendo.

Y la moraleja de esta historia es que cualquier novedad, por insignificante que parezca, requiere dedicar al menos unos minutos de estudio y asimilación, pues esto puede marcar la diferencia entre una aplicación que funciona y otra que no.

Publicado en Variable not found.

Comments



All Copyrights Reserved

Code Variables

2019