En .NET, es bastante habitual que nuestros métodos o funciones reciban objetos de tipo IEnumerable<T> con la intención de que iteremos sobre ellos para lograr el comportamiento deseado. Esta abstracción es muy poderosa, ya que nos permite trabajar con cualquier colección o secuencia de datos sin preocuparnos por su implementación concreta, pero, si no somos cuidadosos, puede llevarnos a errores y comportamientos inesperados.
Por ejemplo, es muy frecuente realizar múltiples enumeraciones sobre la misma instancia de IEnumerable<T>, algo que a veces puede ocurrir de forma inconsciente, y se convierte en un problema cuando la secuencia es muy extensa o su contenido no es replicable. De hecho, muchas herramientas y entornos de desarrollo nos advierten sobre este problema durante la edición y compilación para que estemos atentos.
Otro problema común es asumir que la secuencia es finita, algo que no tiene por qué ser siempre cierto. Las enumeraciones en este caso pueden llevar a bucles infinitos o a un consumo excesivo de recursos.
En este artículo exploraremos distintos escenarios que pueden darse y cómo podemos evitarlos.
Esta semana me he topado con bastantes contenidos interesantes 😊
Por citar algunos, ya tenemos aquí la segunda preview de .NET 11, con novedades interesantes como el runtime asíncrono, soporte nativo para trazas alineadas con OpenTelemetry, mejorillas en Blazor, soporte para OpenAPI 3.2.0, nuevas plantillas de proyecto, mejoras en rendimiento y más. Si quieres conocer todos los detalles, no te pierdas el anuncio oficial.
Bipin Joshi nos habla de las Minimal APIs una vez pasó el hype inicial: qué nos aportan, las ventajas e inconvenientes de su ausencia de código ceremonial y sus escenarios de uso ideales.
Gurveer Arora continúa exprimiendo el potencial de HTML y CSS con su serie NoJS, y en esta ocasión nos trae un clon de Flappy Bird hecho sin una sola línea de JavaScript. Porque poderse, se puede.
También me ha parecido interesante la lectura de The WebAssembly Component Model, una arquitectura para la construcción de librerías y aplicaciones interoperables utilizando WebAssembly.
Y Ricardo Peres continúa explorando las APIs de sincronización en .NET, y en esta ocasión nos habla de las herramientas que tenemos a nuestra disposición para sincronizar distintos procesos, como Mutex, Semaphore y EventWaitHandle.
El resto de enlaces, a continuación.
Por si te lo perdiste...
- ¡Cuidado con las excepciones no controladas de servicios en segundo plano (BackgroundService) en ASP.NET Core!
José M. Aguilar - Antipatrones de asincronía en C#
José M. Aguilar
.NET
- .NET 11 Preview 2 is now available!
.NET Team - Splitting the NetEscapades.EnumGenerators packages: the road to a stable release
Andrew Lock - FullJoin in .NET 11
Steven Giesel - .NET Synchronisation APIs - Part 2 - Out-of-Process Synchronisation
Ricardo Peres
Ya he publicado los enlaces a contenidos interesantes que he ido descubriendo a lo largo de la semana pasada 😊
En esta entrega, destacamos el repaso de Martin Stühmer a los errores más comunes en la gestión de sesiones en aplicaciones ASP.NET Core y cómo evitarlos para mejorar su seguridad de nuestras aplicaciones.
Se ha lanzado la versión 1.0 del SDK oficial de MCP para C#. Aún no he tenido tiempo de probarlo, pero así al vistazo parece que puede facilitarnos un poco la vida a la hora de integrar nuestras aplicaciones con modelos de lenguaje y otros servicios de IA.
Y seguimos con más lanzamientos, Jetbrains han anunciado ReSharper para Visual Studio Code, Cursor y editores compatibles. Como fan incondicional de esta herramienta desde hace años, me alegra que ahora esté también disponible más allá de Visual Studio.
Por último, Gerson Azabache nos recuerda la importancia de hacer ejercicio, especialmente para los desarrolladores, que pasamos muchas horas sentados frente al ordenador y a menudo descuidamos nuestra salud física.
Muchos más enlaces a contenidos interesantes, a continuación.
Por si te lo perdiste...
- Gestión centralizada de paquetes NuGet en soluciones y proyectos .NET
José M. Aguilar - Si las shadow properties no existen como propiedades en la entidad, ¿cómo podemos inicializarlas en el seed de Entity Framework Core?
José M. Aguilar
.NET
- Why IEnumerable Can Kill Performance in Hot Paths
Ali Hamza Ansari - Creating case-sensitive folders on Windows using C#
Gérald Barré - Writing a .NET Garbage Collector in C#
Kevin Gosse
Vamos con una entrega más (siete llevamos ya) de la serie C# bizarro, estos divertidos posts donde ponemos a prueba nuestros conocimientos del lenguaje mientras exploramos algunas de sus características extrañas o poco conocidas.
En esta ocasión, os propongo que le echéis un vistazo al siguiente código, en especial a su método ChangeIdentity(), que pretende cambiar la identidad de una persona por la de otra que le llega como parámetro:
var john = new Person() { Name = "John" };
var peter = new Person() { Name = "Peter" };
john.ChangeIdentity(peter);
Console.WriteLine(john.Equals(peter));
struct Person
{
public string Name;
public void ChangeIdentity(Person otherPerson)
{
this = otherPerson; // WFT!?!?
}
}
En efecto, en el cuerpo del método estamos asignando un nuevo valor a this. ¿Pensáis que esto compilará? Y en caso afirmativo, ¿qué veríamos en la consola al ejecutarlo, true o false?
Deteneos un poco en el código y pensad en la respuesta, que, aunque tiene algo de truco, seguro que podéis encontrarla porque no es muy retorcida. Pero si se resiste o no lo tenéis claro, siempre podréis pulsar aquí para leer la solución 👇👇
El código, efectivamente, compila sin problema. Aunque la asignación de this pueda parecer extraña, es perfectamente válida en C# porque estamos en el interior del método de instancia de una estructura. No compilaría, en cambio, si Person fuera una clase.
Esto se debe a que internamente las estructuras son tipos valor, por lo que this representa una copia completa del valor de la estructura en memoria. Al asignar this = otherPerson, estamos copiando el valor de otherPerson sobre this, lo que en la práctica significa que estamos copiando el valor de todos los campos de la estructura origen sobre la actual, aunque sin tener que hacerlo de forma manual 🙂
En clases, sin embargo, this es una referencia (o puntero) inmutable a la instancia del objeto en memoria, por lo que no se puede reasignar para ponerla apuntando a otro objeto.
Ahora vamos con la segunda parte de la pregunta, ¿qué veremos en la consola al ejecutar el código que utiliza el método ChangeIdentity()?
var john = new Person() { Name = "John" };
var peter = new Person() { Name = "Peter" };
john.ChangeIdentity(peter);
Console.WriteLine(john.Equals(peter));
Seguro que habéis adivinado que la respuesta es true. Fijaos que si hubiésemos utilizado clases en lugar de estructuras, el resultado habría sido false, ya que john y peter serían punteros a objetos distintos en memoria y la igualdad por referencia nunca sería cierta. Pero al ser estructuras, la comprobación de igualdad se realiza por valor, es decir, comparando los valores de todos sus campos.
Y dado que anteriormente hemos copiado los valores de todos los campos de peter sobre la estructura john, ambos objetos son idénticos en memoria y, por tanto, la operación de comparación devuelve true.
Qué, ¿lo habíais adivinado? 😄
Publicado en Variable not found.
Una semana más, vamos con los enlaces a contenidos interesantes que he ido recopilando durante estos días, entre los que destaco algunos posts.
Juan Irigoyen comparte sus experiencias utilizando IA para optimizar SQL Server, en un interesante recorrido por la preparación de un agente Claude capaz de analizar y optimizar consultas SQL, con resultados bastante prometedores.
La depuración puede ser una labor compleja, intensa, a veces frustrante y otras gratificante, pero sin duda forma parte de nuestro día a día. En este artículo, Jeremy D. Miller reflexiona sobre el proceso de depuración, compartiendo consejos para abordar los problemas de manera efectiva-
Y para terminar, una frikada épica a la que llego a través de Microsiervos: un procesador x86 completo implementado únicamente con CSS, sin una sola línea de código JavaScript, y que es capaz de ejecutar código ensamblador compilado para ese procesador.
El resto de contenidos interesantes, a continuación.
Por si te lo perdiste...
- Trocear predicados para mejorar la legibilidad
José M. Aguilar - Shadow properties en Entity Framework Core
José M. Aguilar
.NET
- Logging Profesional en .NET con Serilog: Minimalismo Bien Hecho
Gerson Azabache Martínez - When to Use Builder Pattern in C#: Decision Guide with Examples
Nick Cosentino - A smarter way to learn .NET without reading the docs
David Grace - .NET 11 Preview 1 Arrives with Runtime Async, Zstandard Support, and C# 15 Features
Almir Vuk - Recording metrics in-process using MeterListener
Andrew Lock - Cleaner switch expressions with pattern matching in C#
Bart Wullems - Vector Data in .NET - Building Blocks for AI Part 2
Jeremy Likness - Is it faster to index into an array or use switch statement for lookups?
Jiří Činčura - Semantic Kernel in C#: Complete AI Orchestration Guide
Nick Cosentino - .NET Synchronisation APIs - Part 1
Ricardo Peres - Brave new C#
PVS-Studio - Developing an MCP Server with C#: A Complete Guide
NDepend Team
Otra semana de contenidos interesantes en la web 🙂
Según Milan Milanović, solo 3–4 horas al día son realmente productivas al programar, porque el resto del tiempo se pierde por límites cognitivos, reuniones e interrupciones. Si conseguimos optimizar ese tiempo, mejorará nuestro rendimiento y la calidad del software que desarrollemos, mucho más que intentar trabajar más horas.
Bruno Capuano nos habla sobre la generación de embeddings, tanto de texto como de imágenes, en nuestro equipo local, y nos presenta una biblioteca de código abierto que ha desarrollado para facilitar esta tarea en .NET.
¿En qué se diferencian las colecciones Readonly de las Immutables? ¿Y qué son las colecciones Frozen? Pues aunque parezcan lo mismo, Davide Bellone nos muestra que son cosas muy diferentes.
La primera preview de .NET 11 ya trae algunas novedades interesantes. Steven Giesel nos muestra que el nuevo runtime async es una realidad, y que va a mejorar mucho el rendimiento de las aplicaciones asíncronas.
El resto de enlaces a contenidos interesantes, a continuación.
Por si te lo perdiste...
- Propiedades semi-automáticas en C#
José M. Aguilar - Evaluación en cliente de EF Core: sus peligros y cómo evitarla
José M. Aguilar
.NET
- Logging profesional en .NET: Diseña Telemetría, no Prints
Gerson Azabache Martínez - Collection Expression Arguments in C# 15 are "out"
Steven Giesel - Writing a native VLC plugin in C#
Martin Finkel - Introducing the Coding Agent Explorer (.NET)
Tore Nestenius - New runtime async is hitting .NET 11
Steven Giesel - Exploring .NET 11 Preview 1 Runtime Async: A dive into the Future of Async in .NET
Laurent Kempé - How to Implement Abstract Factory Pattern in C#: Step-by-Step Guide
Nick Cosentino - Creating standard and "observable" instruments
Andrew Lock - Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks
Davide Bellone - Deep C# - Multicast Delegates and Events
Mike James - T4 templates on modern .NET
Ian Griffiths - Getting Started with .NET Scheduling in Hangfire
Peter Ritchie - NuGet Packages: The Suppliers You Forgot to Audit
Martin Stühmer

