
Ya he comentado alguna vez que el hecho de trabajar a diario con C# no implica que conozcamos todas sus funcionalidades, detalles, trampas y recovecos. Después de muchos años, yo sigo encontrándome sorpresas bastante a menudo.
Hace poco, andaba haciendo algunas pruebas y llegué a un código como el siguiente:
var a = 1;
var (b, c) = 4;
var (d, e, f) = 9;
Console.WriteLine(a + b + c + d + e + f ); // Muestra por consola "14"
Así al vistazo, diréis que el código no compila tal cual, pero la pregunta es: ¿sería posible que compilara y, además, mostrara la salida que pretendemos sin tocar una sola línea de las que vemos ahí?
Si lo pensáis un poco seguro que podéis responder a las preguntas. Y si no, pulsad aquí para ver la solución 👇👇
Pues en efecto, el código tal y como está no compila, así que debemos pasar a la siguiente parte de la pregunta: qué podemos hacer para que compile y, además, muestre por consola el valor que buscamos, sin tocar ni una coma de esas cuatro líneas de código propuesto como punto de partida.
Si nos fijamos bien, la primera línea es una asignación normal, pero en la segunda y tercera línea estamos asignando valores a variables usando sintaxis propia de tuplas. En el fondo, ambas líneas son iguales, y fallan en compilación porque no podemos asignar un entero a un tupla. ¿O quizás sí?
Si recordáis, hace mucho tiempo hablamos por aquí de la deconstrucción de clases, un interesante mecanismo que, al más puro estilo de cheff sofisticado, permitía deconstruir o descomponer objetos en tuplas, simplemente implementando el método Deconstruct()
.
Pues bien, resulta que este método Deconstruct()
puede implementarse de forma externa al tipo que va a ser deconstruido mediante extension methods. Seguro que ya empezáis a ver por dónde van los tiros... 😉 En efecto, podríamos implementar el método extensor Deconstruct()
sobre el tipo int
e introducir en él la lógica que nos interese.
Una posible implementación sería la siguiente, en la que tenemos sobrecargas de Deconstruct()
para dos y tres parámetros de salida, entre los que repartimos equitativamente el valor del entero a deconstruir:
public static class IntegerExtensions
{
public static void Deconstruct(this int i, out int i1, out int i2)
{
(i1, i2) = (i / 2, i / 2);
}
public static void Deconstruct(this int i, out int i1, out int i2, out int i3)
{
(i1, i2, i3) = (i / 3, i / 3, i / 3);
}
}
Si ejecutamos ahora mentalmente el código propuesto, veremos que se cumplen los requisitos iniciales:
var a = 1; // a=1
var (b, c) = 4; // "4" se deconstruye en (2,2). Por tanto: b=c=2
var (d, e, f) = 9; // "9" se deconstruye en (3,3,3). Por tanto, d=e=f=3
Console.WriteLine(a + b + c + d + e + f ); //
1+2+2+3+3+3 -> Muestra "14":
Bonito y maquiavélico uso de tuplas y deconstrucción, ¿verdad? 😉
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: c#bizarro

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Indicios de que tu interfaz de usuario fue creado por un programador
José María Aguilar - 3 formas de saber si un componente se está ejecutando en Blazor Server o WebAssembly
José María Aguilar
.NET Core / .NET
- Compartir un fichero C# entre varios proyectos (sin referencias)
Iván Montilla - Time abstraction in .NET 8
Steven Giesel - Where are Objects Allocated in C#? Understanding Heap and Stack
Gevorg Chobanyan - Use secrets in unit tests
Mark Heath - Expression Trees in C#
Code Maze - Enhancing .NET Hot Reload with CreateNewOnMetadataUpdate, MetadataUpdateHandler and MetadataUpdateOriginalType Attributes
Nick Randolph - Refactoring Change Preventers in C#
Code Maze - How to add Dependency Injection, Configurations, and Logging in a .NET 7 Console Application
Davide Bellone - Introducing Sep - Possibly the World's Fastest .NET CSV Parser
Niels Rasmussen - Reduce heap allocations by using static anonymous functions
Bart Wullems - Span / Memory / ReadOnlySequence in C#
Steven Giesel - Managed vs Unmanaged Code (Garbage Collection) in C#
Code Maze - .NET 8: Why .NET 8 preview doesn’t show up in Visual Studio 2022 ?
Anthony Giretti

Hace unos días hablábamos de la serialización polimórfica en .NET 6, y vimos qué posibilidades teníamos para conseguirlo sin tener que escribir un custom converter o conversor personalizado. Y aunque realmente .NET 6 permite hacerlo, no es lo más elegante del mundo porque teníamos que operar sobre tipos object
.
Pero por suerte, en .NET 7 la cosa ha mejorado y ya tenemos opciones razonables para conseguirlo basadas en los dos nuevos atributos [JsonDerivedType]
y [JsonPolymorphic]
. Veamos cómo utilizarlos.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Un vistazo a los patrones relacionales y combinadores, lo nuevo de C# 9 para exprimir el pattern matching
José María Aguilar - El patrón Post-Redirect-Get
José María Aguilar
.NET Core / .NET
- Timers en .Net
Fernando Escolar - nameof get's a bit better in C# 12
Steven Giesel - How to Use SFTP For Secure File Upload in .NET
Code Maze - Getting .NET Library Projects to Output Dependent Assemblies
Rick Strahl - What's the latest .NET roadmap?
Steve Smith - Memory Allocation Optimization With BenchmarkDotNet
Code Maze - How to Convert a String to a Span in C#
Code Maze - Step-by-Step Guide to Adding and Removing Watermarks in PDF using C#
Sameerkhan - New Terminal logger for .NET 8
Steven Giesel - Raiders of the lost root: looking for memory leaks in .NET
Christophe Nasarre - VerificationException in .NET Framework when using structs
Kevin Gosse - .NET 7–Serialize private fields and properties
Bart Wullems - Implicit Operators in C# and How To Create a Multi Type
Nick Cosentino - .NET Micro-Optimization and Refactoring Trick
Patrick Smacchia

Imaginad una clase como la siguiente, que representa las características básicas de los archivos almacenados en una aplicación:
public class File
{
public string FileName { get; set; }
public ulong SizeBytes { get; set; }
}
Y ahora, imaginemos también una clase que hereda de la anterior para modelar específicamente, aunque también de forma resumida, los archivos de vídeo:
public class VideoFile: File
{
public string Codec { get; set; }
public TimeSpan Duration { get; set; }
}
Y puestos a imaginar, acabemos con el siguiente método, que retorna la representación JSON del objeto File
que recibe como parámetro:
string SerializeFile(File file) => JsonSerializer.Serialize(file);
Gracias al polimorfismo, ese pilar imprescindible de la Programación Orientada a Objetos, podríamos invocar este método con objetos de tipo File
, VideoFile
o cualquier descendiente de alguno de ambos, puesto que en todos los casos se trata de objetos de tipo File
:
var file = new File
{
FileName = "file.txt", SizeBytes = 1024
};
Console.WriteLine(SerializeFile(file));
var videoFile = new VideoFile
{
FileName = "video.mp4",
SizeBytes = 1024 * 1024,
Codec = "H264",
Duration = TimeSpan.FromMinutes(3)
};
Console.WriteLine(SerializeFile(videoFile));

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Inicializar a null propiedades sin tipo
José María Aguilar - Cómo saber si un objeto no es nulo (edición C# 9)
José María Aguilar
.NET Core / .NET
- Building a Dynamic Logical Expression Builder in C#
Yohan Malshika - Building Functional .NET Applications: a Guide for Choosing between Nahla Davies
- Detect Globalization-Invariant mode in .NET
Gérald Barré - Understanding the C# Init Operator
Bradley Wells - C# logging: Best practices in 2023 with examples and tools
Shane Duggan - How to Convert Stream to Byte Array in C#
Januarius Njoku - The Ultimate .NET Version Guide
Claudio Bernasconi - How to automatically update a Windows Forms Application?
Renato Ivanescu - .NET 7: Simplify Patch requests with PatchAsJsonAsync extension
Anthony Giretti - 6 useful extensions for IEnumerable
Steven Giesel - Understanding IOptions, IOptionsMonitor, and IOptionsSnapshot in .NET 7
Davide Bellone - Is WPF Dead? - The Current State of WPF [2023]
Claudio Bernasconi - Common C# exceptions and how to fix them
Carlos Schults - How does TryGetNonEnumeratedCount work?
Steven Giesel - How to Generate Permutations in C#
Matjaz Prtenjak - Refactor your .NET HTTP Clients to Typed HTTP Clients
Tim Deschryver - Feature toggle management in .NET Core
Krzysztof Begiedza - .NET Core–Monitor cache misses
Bart Wullems
Hace pocos meses hablábamos de la vuelta del clásico [OutputCache]
en ASP.NET Core 7 y veíamos cómo podía simplificarnos la vida a la hora de cachear en el servidor respuestas de peticiones.
Haciendo un rápido recordatorio, la novedad era la posibilidad de introducir en el pipeline el middleware OutputCacheMiddleware
, que se encargaría de almacenar las respuestas de endpoints y reutilizarlas en posteriores peticiones que cumplieran los requisitos apropiados.

Tras una semana de parón por una semanilla de relax en Roma (ciudad que, por cierto, os recomiendo que visitéis si no lo habéis hecho ya), ahí van los enlaces recopilados durante los últimos días. Como de costumbre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Comprometidos o involucrados?
José María Aguilar - Crear bloques de código Razor reutilizables en Blazor con Render Fragments
José María Aguilar
.NET Core / .NET
- Top 5: Errores de performance en C#
Fernando Escolar - Announcing .NET 8 Preview 4
Jon Douglas - Serilog project update, May 2023
Nicholas Blumhardt - Control Visual Studio from an external application
Gérald Barré - Seamlessly Import and Export CSV Data in Excel Using C#
Mohan Chandran - Prevent .NET Application Insights telemetry loss
Anthony Simmon - Exploring Code Performance Testing in C# with BenchmarkDotNet
Kostis Grontis - Why do we need Wait() and Pulse() Methods in C# Threading?
Kulasangar Gowrisangar - Introduction - Rust for C#/.NET Developers
Atif Aziz et al - Upcoming availability of .NET Framework 4.8.1 on Windows Update and Catalog
Brett Lopez - Multidimensional Array vs Jagged Array in C#
Dusko Mirkovic - URI Encode and Decode in .NET
Code Maze - Concurrent Hosted Service Start and Stop in .NET 8
Steve Gordon - Hot Reload Supports Modifying Generics!
Mikelle Rogers - Client Support for Calling WCF/CoreWCF with System.ServiceModel 6.0 Is Here!
Sam Spencer - C# Tip: Advanced Switch Expressions and Switch Statements using filters
Davide Bellone - TaskCompletionSource Pitfalls
Stephan Gay - Struct vs. Record vs. Class in C#
A. Yohan Malshika - An alternative approach to structuring your tests in XUnit
Bart Wullems - Exploring the C# Source Link Feature: Enhancing Debugging Experiences
Neel Bhatt - XML Serialization in C# .NET Core: A Comprehensive Guide
Sanjay M.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo mostrar por consola las líneas que se van añadiendo a logs o archivos de texto, en tiempo real
José María Aguilar - Métodos condicionales en .NET
José María Aguilar
.NET Core / .NET
- C# Record Type: Nondestructive Mutation, Equality, DTOs, and More
Bradley Wells - Verifying your DI Container
Steven Giesel - Reading Windows Application Manifest of an exe in .NET
Gérald Barré - Calling internal ctors in your unit tests”
Phil Haack - Using sizeof() Operator in C#
Code Maze - How to Create a Custom Slack Bot with .NET 7
Daniel Donbavand - How to convert audio to different formats using C# and FFmpeg
Niels Swimberghe - Dot Net Office : Top Microsoft NuGet Packages in 2023
Dot Net Office - Prevent a Hangfire job from running when it is already active
Tim Deschryver - Controlling the log level of your application
Steven Giesel

El 8 de mayo de 2006 decidí subir a un tren, teniendo más o menos clara la dirección, pero sin saber en qué parada me bajaría.
Cuando en aquél post inicial decía literalmente "espero que el viaje sea largo", probablemente no me refería a tan largo. Aún con la tenacidad de la que hacía gala, era imposible imaginar que diecisiete años después seguiría por aquí, contemplando el paisaje y escribiendo sobre lo que veo, intentando contribuir a una comunidad a la que tanto debo.
Más de 1.430 posts, más de 3.000 comentarios de lectores, más de cinco millones de consultas... pero sobre todo, muchísimo aprendido por el camino y, con suerte, espero que no solo por mi parte 😉

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Aspectos a tener en cuenta al crear sitios web públicos
José María Aguilar - Syncfusion Blazor UI components library: un primer vistazo
José María Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit 8.2! Faster generators, code fixers, performance improvements and more!
Sergio Pedri - C# 11 features I like the most
Neel Bhatt - How to Run an Async Method Synchronously in .NET
Code Maze - Deterministic Finalization in C#: IDisposable and Best Practices
Bradley Wells - A reminder to consider that your context, isn’t the only context (.NET 8 TimeProvider edition)
João Antunes - 10 Awesome C# Refactoring Tips
Assis Zang - Applying the decorator pattern in .NET Core using Castle.DynamicProxy
Bart Wullems - Some basic query support for System.Text.Json
Josef Ottosson

Atributos como [FromRoute]
, [FromForm]
, [FromQuery]
o [FromBody]
, entre otros, permiten ser muy precisos a la hora de indicar al framework cómo poblar los parámetros de los handlers de nuestros endpoints contruídos con Minimal APIs.
Por ejemplo, en la siguiente API sencilla se puede intuir que el parámetro id
del manejador será obtenido de la ruta, mientras que number
se obtendrá desde la query string:
app.MapPost("/friends/{id}/phones", ([FromRoute] int id, [FromQuery] string number) =>
{
// Añadir un número de teléfono al amigo
});
Y otro ejemplo, en el que usamos [FromBody]
para especificar que el parámetro de tipo Friend
queremos obtenerlo desde el cuerpo de la petición:
app.MapPut("/friends/{id}", ([FromRoute] int id, [FromBody] Friend friend) =>
{
// Actualizar amigo
});

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Cuánto pesa realmente una aplicación Blazor WebAssembly recién creada?
José María Aguilar - Y todavía otras 101 citas célebres del mundo de la informática
José María Aguilar
.NET Core / .NET
- Trabajos en segundo plano en .Net
Fernando Escolar - Property Ordering in C# JSON Serialization
Code Maze - WireMock.NET - Troubleshooting
Cezary Piątek - Short Circuit Evaluation of IF Statements with Await in C#
Code Maze - Covariance and Contravariance in C#
Steven Giesel - Reduce Collection Lookups With ReSharper
Maarten Balliauw - Setting an Absolute Output Path for .NET SDK Projects
Rick Strahl

Versión tras versión, Entity Framework Core sigue introduciendo novedades que lo hacen cada vez más potente y atractivo para los desarrolladores. Sin ir más lejos, EF7, la última entrega disponible, incorporó bastantes mejoras en términos de rendimiento, soporte para columnas JSON, mapeo TPC, mapeo a procedimientos almacenados y muchas otras.
Pero una de las novedades que me resultó más interesante, quizás por ser muy esperada, fue la posibilidad de realizar borrados y actualizaciones de forma masiva sin tener que recurrir a lanzar directamente comandos SQL. O dicho de otra forma, con EF7 podremos ejecutar sentencias DELETE
y UPDATE
sobre la base de datos sin abandonar LINQ :)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Palabras malditas
José María Aguilar - Analiza tu código a fondo y desde distintas perspectivas con NDepend
José María Aguilar
.NET Core / .NET
- Announcing .NET 8 Preview 3
Jiachen Jiang - Check out new C# 12 preview features!
Kathleen Dollard - Convert HTML to PDF Report in .NET
Abdul Rahman Shabeek Mohamed - How to Do an Inner Join in LINQ?
Code Maze - Run dotnet core projects without opening visual studio
Karthik Chintala - Investigating a crash in Enumerable.LastOrDefault with a custom collection
Gérald Barré - 5 useful extensions for Task<T> in .NET
Steven Giesel - Normalize and compare URLs with C#
Thomas Ardal - Using Application Insights in .NET Desktop Applications
Rick Strahl - Working With Nested Tasks
Pawel Woltschkow - Producing and Consuming Kafka Messages in CloudEvents Format Using the C# SDK
Vasil Kosturski - Why my WireMock mocks aren't working?
Daniel Genezini - C# Tip: Access items from the end of the array using the ^ operator
Davide Bellone - Static Fields Are Evil, If Not Coded Correctly
David McCarter - Upcasting and Downcasting in C#
Code Maze - .NET 8 Performance Edition
Steven Giesel - Converting Strings to .NET Objects – IParsable and ISpanParsable
Christian Nagel - Performance: The Fastest Way to Use Regular Expressions in Microsoft .NET 7
David McCarter - Different Ways to Split a String in C#
Code Maze - C#12 class and struct Primary Constructors
Patrick Smacchia

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- El hombre que inventó el Control-Alt-Suprimir
José María Aguilar - C# source generators: un ejemplo sencillo, paso a paso
José María Aguilar
.NET Core / .NET
- Looking at C# 12 Proposals and Beyond
Michael Shpilt - LINQ on steroids with SIMD
Steven Giesel - Does OpenTelemetry in .NET Cause Performance Degradation?
Martin J. T. - Refactoring Object-Orientation Abusers in C#
Code Maze - WireMock.NET - Introduction
Cezary Piątek - An abstract example of refactoring from interaction-based to property-based testing
Mark Seemann - How to Remove All Whitespace Characters From a String in C#?
Code Maze - Source Generators and Regular Expressions
Steven Giesel - Listing all available ETW events in a .NET application
Gérald Barré - Working with Tuple in C#
A. Yohan Malshika - C# 11.0 new features: Span<char> pattern matching
Ian Griffiths - Pythonnet – A Simple Union of .NET Core and Python You’ll Love
Nick Cosentino

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- C# Source generators: metaprogramación en tiempo de compilación
José María Aguilar - Desmitificando las expresiones lambda (I)
José María Aguilar
.NET Core / .NET
- How to create a NuGet metapackage
Daniel Wertheim - C# Source Generators: How to get build information?
Steven Giesel - Handling CancelKeyPress using a CancellationToken
Gérald Barré - Deep Copy of an Object in C#
Code Maze - Understanding the .NET ecosystem: The introduction of .NET Standard
Andrew Lock - Primary Constructors with C#
Christian Nagel - Improving multi-platform container support
Richard Lander - How to Delete Elements from an Array in C#
Code Maze - Using the contents of a file to define an MSBuild property
Raymond Chen - C# - Clean up your exception handling logic with Exception Filters
Bart Wullems - Using System.Text.Json to do polymorphic Json conversion in .NET 6
Allan Thraen - Observability in Wolverine
Jeremy D. Miller - Vendor-Agnostic Telemetry Using OpenTelemetry Collector in .NET
Phil Broderick - Change the ServiceLifetime after the service has been added to the .NET ServiceCollection
Niels Swimberghe

A raíz del artículo publicado hace algunas semanas sobre las ventajas de usar diccionarios en lugar de listas, me llegaba vía comentarios un escenario en el que se utilizaba una clase List<T>
para almacenar objetos a los que luego se accedía mediante clave. Lo diferencial del caso es que dichos objetos tenían varias claves únicas a través de las cuales podían ser localizados.
Por verlo por un ejemplo, el caso era más o menos como el que sigue:
public class FriendsCollection
{
private List<Friend> _friends = new();
...
public void Add(Friend friend)
{
_friends.Add(friend);
}
public Friend? GetById(int id)
=> _friends.FirstOrDefault(f => f.Id == id);
public Friend? GetByToken(string token)
=> _friends.FirstOrDefault(f => f.Token == token);
}
Obviamente en este escenario no podemos sustituir alegremente la lista por un diccionario, porque necesitamos acceder a los elementos usando dos claves distintas. Pero, por supuesto, podemos conseguir también la ansiada búsqueda O(1) si le echamos muy poquito más de tiempo.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Formas de relanzar excepciones en C#
José María Aguilar - Cómo crear bibliotecas de clases o proyectos de consola .NET 5 en lugar de .NET Core 3.1
José María Aguilar
.NET Core / .NET
- Adding Dependency Injection to a Console App in .Net 7
Paul Michaels - Loading RSA Keys in .NET & Loading RSA Keys in .NET
Scott Brady - How to Use MemoryStream in C#
Ivan Matec - Too many timers in .NET?
Gérald Barré - Implementing React's UseState in C#
Ricardo Peres - Understanding the .NET ecosystem: The evolution of .NET into .NET 7
Andrew Lock - Caching in .NET with MemoryCache
Steven Giesel - The Top .NET C# UI Controls You Should be Using
GrapeCity Developer Solutions - Iterator Benchmarks That Shocked With Unexpected Results
Nick Cosentino - .NET 8 Preview 2 Unveiled: 5 New Features You Need to Know
ByteHide - .NET Performance Delivers Again for Bing, From .NET 5 to .NET 7
Ben Watson - Secure your .NET cloud apps with rootless Linux Containers
Richard Lander - How to build a URL Shortener with C# .NET and Redis
Niels Swimberghe - .NET Core - Remove older SDKs and runtimes
Bart Wullems - How to Create a Custom JsonConverter in Json.NET
Ahsan Ullah - Leverage 'is not' Operator for Exception Filtering!
Steven Giesel

El pattern matching de C# proporciona la capacidad de analizar expresiones para ver si cumplen determinados "patrones" o presentan características determinadas. Podéis ver algunos ejemplos interesantes en el post Un vistazo a los patrones relacionales y combinadores.
Aunque ya los tengo bastante interiorizados y hago uso de ellos cuando toca, todavía no se me ha dado el caso de necesitar los patrones de listas, introducidos hace unos meses en C# 11. Así que no está de más echarles un vistazo para cuando se dé la ocasión 😉

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Radzen Blazor Components: ¡ahora open source!
José María Aguilar - Usando using, valga la redundancia (C#)
José María Aguilar
.NET Core / .NET
- Announcing .NET 8 Preview 2
Alexandra Barry - .NET 7 SDK built-in container improvements
Laurent Kempé - System.Text.Json Serializing Hierarchical Data
Christian Nagel - Partial Classes In C# And How to Use Them
Code Maze - Solving .NET JSON Deserialization Issues
Khalid Abuhakmeh - Using Trie Class for Efficient Text Pattern Searching in C#
Code Maze - How Async/Await Really Works in C#
Stephen Toub - Immutable Collections in C#
Code Maze - WkHtmlToPdf: Dealing with broken Url Encoded and Extended Character Links
Rick Strahl - Enhancing JPEG, PNG, Text Using C# .NET Part 1
GrapeCity Developer Solutions - Polly with .NET 6, Part 8 - Policy Registry with Minimal APIs, and HttpClientFactory
Bryan Hogan - Discover the New Features of .NET 8: What You Need to Know
ByteHide - Many Ways to make and Deserialize an HTTP GET with HttpClient
Bryan Hogan - Write your own AutoMapper in C#
Steven Giesel

A veces, los problemas de rendimiento de las aplicaciones, o determinadas funcionalidades de ellas, vienen derivados del uso de estructuras incorrectas para almacenar los datos, ya sea en memoria, base de datos o en cualquier tipo de almacén.
En este post vamos a centrarnos en un caso específico que me he encontrado demasiadas veces en código real: el uso indebido del tipo List<T>
cuando sólo nos interesa buscar en esta colección por una propiedad que actúa como identificador único del objeto T
.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Si usas [EmailAddress] y [Url] para validar datos de entrada, ojo: ¡que hace tiempo que ya no validan mucho!
José María Aguilar - 101 formas de saber que tu proyecto está condenado al fracaso
José María Aguilar
.NET Core / .NET
- Gestionando la configuración de nuestras aplicaciones (1/x)
Sergio Navarro Pino - Delegados en C#
Benjamín Camacho - What's new for the WinForms Visual Basic Application Framework
Klaus Loeffelmann - Announcing ImageSharp 3.0.0
Siz Labors - We want your feedback! Introducing Polly v8
Joel Hulen - What really is the Entry Point of a .NET Module?
Washi - Understanding LINQ Deferred, Immediate, Streaming and Non-Streaming Executions
Abdul Rahman Shabeek Mohamed - .NET Console Application with injectable commands
Kees C. Bakker - Validating Connection Strings on .NET Startup
Khalid Abuhakmeh - Testing Roslyn Incremental Source Generators
Gérald Barré - How to Setup Integration Tests in .NET Without a WebApplicationFactory
Paul DeVito - How To Use The yield break Statement In C#?
Muhammed Saleem - How to Find the Caller Method in C#
Code Maze - Implementing the Producer Consumer Pattern with TPL Dataflow
Mark Heath - Alternative Way of Logging With OpenTelemetry Logging in .NET
Phil Broderick - Manipulating CSV Files in .NET
Assis Zang

Si desarrollas APIs, probablemente utilizarás Postman, Fiddler o herramientas similares para probarlas. Cualquier utilidad capaz de lanzar peticiones y analizar la respuesta, incluso basadas en línea de comandos como el desconocido Dotnet HTTP REPL, viene de perlas para ponernos en el lugar del cliente y comprobar cómo responde nuestra API ante determinados parámetros de entrada, o qué se siente al consumirla.
Tiempo atrás, el descubrimiento de la extensión REST client para Visual Studio Code supuso una bocanada de aire fresco en la forma de lanzar peticiones y examinar respuestas, para mi gusto mucho más cómoda que las que estaba acostumbrado a utilizar. Esta extensión permite definir peticiones HTTP en archivos de texto con extensión .http
o .rest
y ejecutarlas de forma realmente sencilla, sin abandonar el IDE.
Pues bien, la última revisión de Visual Studio 2022 (17.5) ha incluido el soporte nativo para este tipo de archivos, así que cada vez lo tenemos más sencillo. Y como es posible que alguno de vosotros aún no lo conozca, vamos a echarle un vistazo ;)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Programadores con producción neta negativa (NNPP)
José María Aguilar - Trimming de espacios no significativos en Blazor 5
José María Aguilar
.NET Core / .NET
- Get Seamless Network Communication with These .NET Classes
Admir Mujkic - C# Tip: Initialize lists size to improve performance
Davide Bellone - How to Improve Enums With the SmartEnum Library
Code Maze - Extending the System Menu to add advanced commands in .NET
Gérald Barré - What To Be Wary of With Iterators and Collections in C#
Nick Cosentino - Raw Strings, UTF-8 Strings, and Multiline Interpolations – Using C# 11 in Rider and ReSharper
Sasha Ivanova - C# FileStream For Lazy Developers In A Hurry. The Bare Minimum
Gus Pear - Resiliency with Wolverine
Jeremy D. Miller - Speed Up ASP.NET Core JSON APIs with Source Generators
Khalid Abuhakmeh - IEnumerable, ICollection, IList and List
Code Maze - Write a high-quality README for NuGet packages
Lynn Dai - Microsoft Teams' Permission Service migration to .NET 6
Diogo Barbosa

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Iterar con foreach sobre cualquier tipo de objeto con C#9
José María Aguilar - Visualizar archivos de ayuda .CHM descargados de Internet
José María Aguilar
.NET Core / .NET
- C#: enum
Fernando Escolar - Announcing .NET 8 Preview 1
Jeremy Likness - error NETSDK1194: The "--output" option isn't supported when building a solution.
Steven Giesel - Building Functional .NET Applications: a Guide for Choosing between Nahla Davies & Daniel Bryant
- How safe are .NET serialization libraries against StackOverflowException
Nemanja Mijailovic - Refactoring huge C# code base in minutes
Laurent Kempé - Creating a custom Main method in a WPF application
Gérald Barré - List and Span Pattern Matching – Using C# 11 in Rider and ReSharper
Sasha Ivanova - Create Clean Guard Clauses With GuardClauses in C# Code Maze
Code Maze - Resolving the Call Is Ambiguous Error While Using LINQ
Code Maze - C# "var" with a Reference Type is Always Nullable
Jeremy Clark - Getting git version information in your C# code
Steven Giesel - Safer Nullability in Modern C#
Matt Eland - C# 11.0 new features: newlines in string interpolation expressions
Ian Griffiths - Automatic Instrumentation of Containerized .NET Applications With OpenTelemetry
Rahul Rai - How Hangfire Helps Your .NET API Perform Out-of-Process Tasks with Resilience and Speed – Wrapt
Paul DeVito - Windows Forms Binding Improvements in .NET 7 for MVVM Support Edin Kapić
- C# 11–The scoped keyword
Bart Wullems

Aunque muchos de nosotros trabajamos a diario con C#, siempre hay algo nuevo por aprender o formas de utilizar algunas características que nunca se nos habían ocurrido. Siempre.
En un nuevo capítulo de la serie de C# bizarro, hoy os planteo un reto sobre este código:
var sum = (int a, int b) => a + b;
var sub = (int a, int b) => a - b;
var mul = (int a, int b) => a * b;
var result = sum - sub + mul;
Console.WriteLine("Resultado: " + result(3, 2));
¿Compila? Y si es así, ¿qué aparece por consola? ¡No sigáis leyendo! Echad un vistazo al código e intentad averiguarlo antes de ver la solución pulsando aquí :)
Pues sí, este código es totalmente válido y compilará sin problema. Y al ejecutarlo, por consola veremos lo siguiente.
Resultado: 6
En primer lugar el código compila correctamente porque las variables sum
, sub
y mult
, que hemos definido usando expresiones lambda de tipo Func<int, int, int>
, a la postre son simplemente delegados.
Además, los tres delegados tienen la firma idéntica (reciben dos valores int
y retornan un int
), podemos utilizar los operadores de combinación suma "+
" y resta "-
", lo que da lugar a un delegado de multidifusión (multicast delegate).
En nuestro código, creamos el nuevo delegado de multidifusión result
combinando sum
y mult
, que son los dos delegados que se suman. Por otra parte, la resta de sub
es simplemente una maniobra de distracción, pues se intentará eliminar de la combinación un delegado que no existía previamente, por lo que la operación será ignorada.
var result = sum - sub + mul;
Tras ejecutar esta línea, result
será un Func<int, int, int>
cuya invocación provocará que se ejecuten secuencialmente, y por orden de llegada, los delegados que han sido combinados.
Por tanto, cuando se evalúa la expresión result(3, 2)
, se ejecutará primero la función sum(3, 2)
y luego mul(3, 2)
, y será el resultado de esta última la que se retorne finalmente. De ahí obtenemos el 6
que va a la consola.
¿Qué, habías acertado?
Publicado en Variable not found.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear componentes de forma dinámica en Blazor
José María Aguilar - 20 desastres famosos relacionados con el software
José María Aguilar
.NET Core / .NET
- Upgrading your .NET projects with Visual Studio
Olia Gavrysh - How to Return a Default Value From a Dictionary in C#
Code Maze - What is .NET, and why should you choose it?
.NET Team - Thoughts on 'What is .NET, and why should you choose it?'
Andrew Lock - Exploring the New Features and Improvements in .NET 7
Vinoth Kumar Sundara Moorthy - How to Get Formatted JSON in .Net Using C#
Code Maze - Async EventHandlers – A Simple Safety Net to the Rescue
Nick Cosentino - Wolverine’s New HTTP Endpoint Model
Jeremy D. Miller - Creating a circuit breaker health check using Polly CircuitBreaker
Jürgen Gutsch - What's On Tap for .NET 8 (Preview 1 Coming this Month)
David Ramel - Digging Into Nullable Reference Types in C#
Shawn Wildermuth - Multipart Form-Data in HttpClient with ASP.NET Core
Code Maze - Prevent accidental disclosure of configuration secrets
Gérald Barré - Removing Manually Installed .NET SDKs from Linux
Bryan Hogan - Creating Visual Studio extensions using Roslyn analyzers
Thomas Ardal - A (performance) quirk with JsonSerializer
Steven Giesel - Getting Started with Generics in .NET
Assis Zang

Hace poco, un alumno de mi curso de Blazor en CampusMVP me preguntaba si, para seguir con las viejas costumbres, desde Blazor Server era posible escribir en la consola del navegador.
Aunque no tiene demasiado sentido hacerlo dado que disponemos de buenas herramientas de depuración, me pareció un ejemplo interesante para aplicar los mecanismos de interoperación de Blazor con JavaScript. Además, quizás interese a alguien más, así que vamos a ver por aquí cómo hacerlo.
Pero antes de meternos en faena, vale la pena decir que lo que veremos no es específico de Blazor Server, sino que también podremos usarlo en Blazor WebAssembly. Los mecanismos básicos de interoperación con JavaScript son idénticos, por lo que en este post veremos cómo implementar un código válido para ambos tipos de hosting.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: blazor, blazorinterop, blazorserver, blazorwasm

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo tomar el control en el momento de la instanciación de componentes Blazor con IComponentActivator
José María Aguilar - Métodos genéricos en C#
José María Aguilar
.NET Core / .NET
- C# Language Mind map
Steven Giesel - Update to the .NET language strategy
Kathleen Dollard - Simple Secrets for Access to the .NET Record Type
Nick Cosentino - Refactoring Bloated Code in C#
Code Maze - Explicit validation in C# just got simpler!
Oskar Dudycz - Asynchronous Programming Patterns in .NET
Code Maze - Must follow C rules, no exceptions
Eric Sink

Me gusta estar atento a las novedades que van apareciendo el lenguajes y frameworks que nos ayudan a mejorar la forma de hacer las cosas. Lamentablemente, en este mundo tan cambiante no es fácil estar al día en todo, y hay muchas veces que sigo haciendo cosas como siempre aunque existan fórmulas más modernas y mejores para conseguirlo.
Un ejemplo lo he encontrado hace poco, cuando, trabajando con JavaScript, una vez más he tenido necesidad de parsear la URL de la página actual en busca de los valores de los parámetros suministrados en la query string al cargar una página. Lo habitual en estos casos era tirar de Google o StackOverflow y acabar implementado una función parecida a la siguiente:
function getParameterValue(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
Casualmente, en este caso recordé haber leído de pasada sobre la existencia de un "nuevo" objeto de JavaScript que actualmente nos permite hacerlo de forma más sencilla, así que aproveché para ponerme un poco al día al respecto ;)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo convertir clases en diccionarios clave/valor
José María Aguilar - 12 novedades destacables de Blazor 5.0 (bueno, y algunas más)
José María Aguilar
.NET Core / .NET
- C# HTML Parser
Manthan Koolwal - How to Get Value by Key from JObject in C#
Code Maze - C# All string escape sequences
Metadata consulting - Hot-reload any Serilog sink
Nicholas Blumhardt - C# Tip: do NOT use nameof to give constants a value
Davide Bellone - Basic Windows Machine Hardware information from WMI for Exception Logging from .NET
Rick Strahl - C# ValueTuple
Patrick Smacchia - C# 11.0 new features: raw string literals
Ian Griffiths - Thread Safe Lazy Initialization Using C# Notes
Ken Dale

Seguimos hablando de problemas que es habitual solucionarlos de una determinada manera, quizás por costumbre, quizás por pereza, o tal vez por desconocimiento de que haya otras formas de hacerlo. En este caso, hablaremos de una necesidad que probablemente habréis tenido alguna vez: transformar un GUID a una cadena de caracteres eliminando los habituales guiones.
Es decir, dado un GUID con el valor 1f5772a6-91ca-4035-8b6d-9676ec6d0eaa
, queremos obtener su representación como cadena de caracteres, pero eliminando los guiones, resultando "1f5772a691ca40358b6d9676ec6d0eaa"
.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Atajo para instanciar tipos anónimos en C# y VB.NET
José María Aguilar - Error 404 cargando páginas Blazor Server con parámetros que contienen un punto
José María Aguilar
.NET Core / .NET
- Cómo corregir una Null Reference Exception
Fernando Escolar - Head and Tail using list patterns in C#
Jiří Činčura - Find total number of ways to reach the n’th stair from the bottom in C#
Dot Net Office - How to modernize a legacy .NET Framework WCF app using CoreWCF and .NET 7
Carlos Pons - Realistic Data Generation in .NET With Bogus
Marko Hrnčić - CSharp dotNET How to remove ASCII Control Characters fast and reduce to ASCII set
Metadataconsulting - Which collection interface to use?
Vladimir Khorikov - Programming SVGs with C#
Khalid Abuhakmeh - Static libraries
Eric Sink - C# 11.0: Generic Math, C# Operators and Static Abstract/Virtual Interface Members
Thomas Claudius Huber - Performance: The Fastest Way to Loop Over an Array in Microsoft .NET
David McCarter - Understanding and Using the ‘Unchecked’ Keyword in C#
Ahmet Burhan Simsek - Using Command Binding in Windows Forms apps to go Cross-Platform
Klaus Loeffelmann - C# Lowering
Steven Giesel - 9 Tips to Reduce WPF App Startup Time
Andrey Slabov - Check If a String Array Contains a Value and Get Index
Code Maze

Ahí van los enlaces recopilados durante una griposa y febril semana pasada. Así que espero que os resulten especialmente interesantes. ;-)
Por si te lo perdiste...
- Detectar la prerenderización en Blazor
José María Aguilar - Cómo crear un traceroute con .NET, paso a paso (y II)
José María Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit 8.1! Better, faster MVVM source generators, .NET 7 support, and more!
Sergio Pedri - Convert GUIDs to a Shorter Textual Representation and Back
Roland Weigelt - .NET 7 Brings Networking Improvements
Edin Kapic - Understanding PLINQ in .NET
Marco Luzzara - Checking for Overflow in C#
Jeremy Clark - C# 12: Primary Constructors
Steven Giesel - Deconstruction in C#
Patrick Smacchia - Property based testing in C#–Part 2
Bart Wullems

Desde la llegada de ASP.NET Core, hace ya algunos años, muchos hemos echado de menos el filtro [OutputCache]
de ASP.NET MVC "clásico". Aunque el nuevo framework ofrece alternativas interesantes para gestionar la caché tanto en el lado cliente como en el servidor, ninguna aportaba las funcionalidades que este filtro nos ofrecía.
Como recordaréis, a diferencia de las opciones ofrecidas actualmente por ASP.NET Core, como el filtro [ResponseCache]
o el middleware ResponseCaching
, que básicamente se regían por los encabezados presentes en peticiones y respuestas HTTP, el filtro [OutputCache]
es una solución de caché residente exclusivamente en el servidor. En este caso, la decisión de si el resultado a una petición se almacena o no se realiza completamente desde la aplicación, de forma totalmente independiente a encabezados o requisitos procedentes del lado cliente.
En ASP.NET Core 7 este filtro ha vuelto a la vida en forma de middleware, que ofrece sus funcionalidades con dos sabores distintos:
- Con anotaciones aplicables a endpoints implementados con Minimal API.
- Como filtro, aplicable a controladores y acciones MVC.
Echémosles un vistazo.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear un traceroute con .NET, paso a paso (I)
José María Aguilar - Cómo personalizar los mensajes de error de conexión en Blazor Server
José María Aguilar
.NET Core / .NET
- No, No, No - Tasks are not threads and they are not for performance!
Steven Giesel - Detecting breaking changes between two versions of a NuGet package at packaging time
Gérald Barré - How to Iterate Over JSON Objects in C#
Code Maze - Deserialize Mastodon User XML RSS feeds with .NET
Khalid Abuhakmeh - LINQ for beginners: pick the right methods!
Davide Bellone - Rebus in .NET - Service Bus Implementation
Phil Broderick - Lazy and once-only C# async initialization
Ian Griffiths - Making an Asynchronous Breakfast in .NET
Assis Zang - 5 new advanced features improving C# 11
Tom Deseyn - Cryptography Implementations in .NET
Alvaro Montoya - Getting rid of warnings with nullable reference types and JSON object models in C#
Maarten Balliauw - Profiling .NET on Linux with BenchmarkDotNet
Adam Sitnik

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Las 10 cosas que más fastidian a los programadores
José María Aguilar - Valores y parámetros en cascada con Blazor
José María Aguilar
.NET Core / .NET
- Understanding Task and ValueTask in C#
Code Maze - Give your strings context with StringSyntaxAttribute
Steven Giesel - ConcurrentBag in C#
Code Maze - Adding NuGet packages when offline
Mark Seemann - Challenge: what does this code print? & The answer
Oren Eini - C# 11 List Patterns - Create compatible types
Gérald Barré - .NET Tips and Tricks & ValueStringBuilder
Steven Giesel - OpenTelemetry in .NET - Basic Usage With Examples
Phil Broderick - ReadOnlySpan<char> and strings
Steven Giesel - How to Use Change Tokens in .NET 7?
Goker Akce - Why tuples in C# are not always a code smell
Dennis Frühauff - Automating Integration Tests using the “Critter Stack”
Jeremy D. Miller - Avoiding Primitive Obsession in .NET
Assis Zang

Ante todo, aprovecharé esta inigualable ocasión para desearos lo mejor para este nuevo año 2023 que se está empezando a dibujar. Espero que tengáis oportunidad de cumplir vuestros proyectos y de disfrutar del camino que os lleve a ellos.
Y para empezar con buen pie, como es habitual, vamos a repasar los 10 artículos más leídos en Variable Not Found durante este 2022 que acaba de terminar.
En septiembre de 1947, Grace Murray Hopper y sus compañeros de la Universidad de Harvard descubrieron, sobre un relé electromagnético de su Mark II, una polilla (en inglés, moth) chamuscada que provocaba que su programa no funcionara correctamente. "No funciona porque aquí hay un bicho", debieron pensar.

Lo primero, aunque llegue algo tarde, aprovecho para desearos unas felices fiestas :)
Y siguiendo con nuestro tema, aunque no está recogido en ninguna RFC ni documento oficial (o al menos no he sido capaz de encontrarlo) el código de error HTTP 509 (Bandwidth Limit Exceeded) suele utilizarse para informar al lado cliente de que la solicitud no puede ser procesada porque el servidor ha sobrepasado el límite de ancho de banda que tenía disponible. Normalmente ocurre cuando el plan del hosting utilizado es insuficiente para manejar el tráfico del sitio web, por lo que debe ser upgradeado para que todo siga funcionando.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo detectar navegadores que no soportan Blazor WebAssembly
José María Aguilar - Crear puntos de ruptura en tiempo de ejecución con .NET
José María Aguilar
.NET Core / .NET
- How to Secure Passwords with BCrypt.NET
Code Maze - Build Your Own Podcast App with .NET 7, Blazor, and .NET MAUI
James Montemagno - Ref-structs are technically obsolete
James Turner - Will ChatGPT replace .NET developers?
David Grace - Delete dotnet bin and obj folders recursively
Steve Smith - Extreme LINQ Performance Boost in .NET 7
Ivan Matec - Generating C# bindings for native libraries by using ChatGPT
Muhammad Azeez - Enhancing the Factory Pattern with C# Attributes
John Patrick Glattetre - Better assertions for your unit tests
Johan Smarius - Microsoft .NET History
Lazie Wouters - Introduction to MVVM Source Generators for C# .NET
Julian Ewers-Peters - Saving Christmas with Functional C#
Simon Painter - IEnumerable in C#
Code Maze - How the heap verification mode helps with debugging heap corruption
Maoni Stephens - C# 11.0: Raw String Literals
Thomas Claudius Huber

Si habéis trabajado algo con Blazor, seguramente sabréis que los componentes escritos en archivos .razor
son traducidos en tiempo de compilación a lenguaje C# y posteriormente compilados como cualquier otra clase de nuestro proyecto.
Por tanto, ¿que impediría que nos saltásemos ese paso y escribiéramos nuestros componentes directamente en C#? Efectivamente, nada ;)
En este post veremos cómo hacerlo.
Pero antes, un disclaimer: apenas existen razones prácticas para implementar componentes visuales usando C#. Usando Razor todo será más sencillo, rápido y tendremos menos riesgo a equivocarnos, así que esa debe ser la opción por defecto. Por tanto, lo que vamos a ver aquí no debéis usarlo salvo en casos justificados (por ejemplo, cuando queráis crear componentes sin UI).