Iterar con foreach sobre cualquier tipo de objeto con C#9 - Code Variables -->
Code Variables Code Variables

Latest news

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

Iterar con foreach sobre cualquier tipo de objeto con C#9

.NET Core

Leyendo las novedades de C# 9, hay una que pasa casi completamente desapercibida pero que me ha llamado la atención: la posibilidad de convertir prácticamente cualquier tipo en enumerable.

La magia consiste en que, a partir de esta versión, se podrá recorrer con un foreach objetos que, o bien implementen IEnumerable o directamente el conocido GetEnumerator(), como lo hacen los arrays o strings, o bien existe un método extensor con el mismo nombre declarado sobre el tipo.

En el blog de Lukáš Lánský encuentro un ejemplo terrorífico, pero a la vez extremadamente clarificador de la potencia de esta posibilidad:

public static class VonNeumannExtensions
{
public static IEnumerator<int> GetEnumerator(this int number)
{
for (var i = 0; i < number; i++)
{
yield return i;
}
}
}

¡Yep! Acabamos de definir el extensor GetEnumerator() sobre el tipo int, lo que quiere decir que ahora podemos recorrerlo con un con  foreach() con total naturalidad:

public class Program
{
public static void Main()
{
foreach (var i in 5) // WTF?
{
Console.WriteLine(i);
}
}
}

Seguro que podéis imaginar el resultado que se mostrará en consola:

0
1
2
3
4

Visto esto, seguro que podemos imaginar otros usos. Por ejemplo, ¿quién no ha querido alguna vez recorrer un rango de valores de esta forma tan limpia?

foreach (var i in 0..9)
{
Console.Write(i);
}
// Output: 0123456789

Pues bastaría con crear el correspondiente extensor para el tipo Range:

public static class RangeExtensions
{
public static IEnumerator<int> GetEnumerator(this Range r)
{
for (int i = r.Start.Value; i <= r.End.Value; i++)
{
yield return i;
}
}
}

Otro ejemplo: imaginad que tenemos una clase Invoice a cuyo código no tenemos acceso, pero deseamos poder recorrer sus líneas de detalle usando foreach. Sería tan sencillo como crear un extensor como el siguiente:

public static class InvoiceExtensions
{
public static IEnumerator<InvoiceLine> GetEnumerator(this Invoice invoice)
{
return invoice.GetLines().GetEnumerator();
}
}

Y a partir de este momento, ya podríamos hacerlo sin problema:

var invoice = _invoices.GetById(18);
foreach (var line in invoice)
{
Console.WriteLine($"{line.Description}, {line.Items} items");
}

¿Utilidad real y práctica de esto? Pues creo que escasa para la mayoría de los mortales. Supongo que habrá algunos escenarios en los que el esfuerzo de haber añadido esta característica al compilador merezca la pena, pero en el día a día creo que no es algo que vayamos a tener que utilizar muchas veces.

Si tenéis interés, podéis echar un vistazo a la entrada en Github donde se discute la funcionalidad y se proponen varios escenarios de uso relacionados con tuplas y tipos genéricos.

En cualquier caso, curioso sí que es ;)

Publicado en Variable not found.

Comments



If you like the content of our blog, we hope to stay in constant communication, just enter your email to subscribe to the blog's express mail to receive new blog updates, and you can send a message by clicking on the button next ...

إتصل بنا

About the site

author Code Variables  Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

Learn more ←

Blog visitors

Blog stats

All Copyrights Reserved

Code Variables

2019