Quantcast
Channel: campusMVP.es
Viewing all articles
Browse latest Browse all 777

C#: Condicionales más simples usando coincidencia de patrones de objetos

$
0
0

[youtube:MljHlwW9Puo]

Normalmente cuando queremos verificar que un objeto cumple con ciertas propiedades utilizamos un condicional escribiendo una y otra vez el objeto para poder hacer la comprobación.

Por ejemplo, en este código hemos definido una clase simple llamada Person e instanciamos un objeto de la misma:

class Person
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

List<Person> personitas = new List<Person>();
	personitas.Add(new Person { Name = "Juan", LastName = "Perez", Age = 20 });
	personitas.Add(new Person { Name = "Elvira", LastName = "García", Age = 24});
	personitas.Add(new Person { Name = "Pedro", LastName = "González", Age = 30});
	personitas.Add(new Person { Name = "Maria", LastName = "", Age = 40});
	personitas.Add(new Person { Name = "José Antonio", LastName = "Español", Age = 50 });

Si ahora quisiéramos sacar una lista con las personas que cumplan con ciertas condiciones, por ejemplo que tengan entre 20 y 40 años y que tengan apellidos haríamos un condicional parecido a este:

List<Person> personitas1 = new List<Person>();
foreach (Person p in personitas)
{
    if (p.Age >= 20 && p.Age <= 40 && p.LastName.Length > 0)
        personitas1.Add(p);
}
Console.WriteLine(personitas1);

No está mal, pero es un poco tedioso escribir todo eso.

Podemos simplificarlo si usamos el método extensor FindAll de Linq aplicándolo a la lista, que toma una expresión lambda para decidir qué elementos encuentra y filtra:

List<Person> personitas1 = personitas.FindAll(p => p.Age >= 20 && p.Age <= 40 && p.LastName.Length > 0);

Aún así demasiado largo.

Podemos simplificarlo gracias a la coincidencia de patrones de C#, que está disponible a partir dela versión 7 del lenguaje y que usa el operador is. Estas expresiones nos permiten comparar un objeto con un patrón para el mismo, siendo más cortos, más claros y ahorrándonos escribir innecesariamente.

Se trata de definir cómo queremos que sea el objeto con el que queremos compararnos, por ejemplo así:

List<Person> personitas1 = personitas.FindAll(p => p is { 
                                                            Age: >= 20, 
                                                            Age: <= 40, 
                                                            LastName.Length: >0
                                                        });

De hecho, lo podemos simplificar usando operadores simples como and, or o not en la expresión de cada propiedad:

List<Person> personitas1 = personitas.FindAll(p => p is 
                                              { 
                                                  Age: >= 20 and <= 40, 
                                                  LastName.Length: >0
                                              });

Esto está muy bien, pero tiene algunas limitaciones, y es que solo podemos emplear constantes para los valores y, además, sólo podemos usar las propiedades y las propiedades de éstas, pero no sus métodos. Así, por ejemplo, si quisiésemos filtrar de este modo a aquellas personas cuyo apellido termine en "ez", nos daría un error:

List<Person> personitas1 = personitas.FindAll(p => p is 
												{
													Age: >=20 and <=40, 
													LastName.Length: > 0,
													p.LastName.EndsWith("ez"): true
												});

¡Esto no es válido!

Tendríamos que combinar la coincidencia de patrones con una condición convencional:

List<Person> personitas1 = personitas.FindAll(p => p is { 
                                                            //Age: >= 20, 
                                                            //Age: <= 40, 
                                                            Age: >= 20 and <= 40,
                                                            LastName.Length: >0
                                                        }&& 
                                                        p.LastName.EndsWith("ez"));

También podemos utilizar propiedades complejas en la coincidencia de patrones. Por ejemplo, supongamos que le añadimos una propiedad Manager de tipo Person para saber de quién dependen en una organización:

class Person
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
	public Person Manager;
}

List<Person> personitas = new List<Person>();
	personitas.Add(new Person { Name = "Juan", LastName = "Perez", Age = 20 });
	personitas.Add(new Person { Name = "Elvira", LastName = "García", Age = 24, Manager = personitas[0] });
	personitas.Add(new Person { Name = "Pedro", LastName = "González", Age = 30, Manager = personitas[0] });
	personitas.Add(new Person { Name = "Maria", LastName = "", Age = 40, Manager = personitas[1] });
	personitas.Add(new Person { Name = "José Antonio", LastName = "Español", Age = 50 });

Ahora podríamos hacer filtros como estos:

List<Person> personitas3 = personitas.FindAll(p => p is {
						Manager.LastName: "Perez"
					 });
Console.WriteLine(personitas3);

Pero mucho cuidado con esto ya que tiene sus limitaciones:

  • Como ya he dicho antes, solo se permiten constantes o literales en el patrón, así que esto daría un error de sintaxis:
string lnManager = "Perez"
List<Person> personitas3 = personitas.FindAll(p => p is {
    Manager.LastName: lnManager
});

Obteniendo un error ya en tiempo de edición:

Error que indica que se espera un valor constante y no una variable

  • Lo de usar propiedades de las propiedades en la expresión sólo funciona con C# 10 o posterior, o sea, con .NET 6 o posterior. Si lo intentamos con una versión más antigua nos dará un error, pero podemos saltarnos la limitación anidando la coincidencia de patrones, así:
List<Person> personitas3 = personitas.FindAll(p => p is {
						Manager: {LastName: "Perez"}
					 });
Console.WriteLine(personitas3);

En resumen

La coincidencia de patrones para propiedades de objetos es una técnica muy útil para ciertos casos que nos permite ahorrar tiempo y mejorar la claridad de lo que estamos haciendo. Aprende a sacarles partido y a utilizarlos en tu código a partir de ahora.

Y si quieres aprenden C# y .NET en serio y no "con alfileres" para no perderte cosas importantes como estas y ser un buen profesional, deberías estudiar con nuestro curso de la Desarrollo con la plataforma .NET y C#

¡No te arrepentirás!


Viewing all articles
Browse latest Browse all 777

Trending Articles