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