Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

18 años online

el blog de José M. Aguilar

Inicio El autor Contactar

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

¡Microsoft MVP!
martes, 26 de diciembre de 2023
--- Enlaces interesantes

Ante todo, aprovecho para desearos felices fiestas y, como no nos veremos por aquí hasta enero, un grandioso 2024. 

Y, por supuesto, ahí van los enlaces recopilados durante la semana pasada que, como siempre, espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 19 de diciembre de 2023
C#

Poco a poco vamos haciéndonos con las novedades de C# 12, y en esta ocasión nos centraremos en una nueva sintaxis que proporciona una forma concisa y rápida para declarar los elementos de una colección.

Ya os adelanto que si sois de los que siempre han envidiado otros lenguajes por la facilidad con la que se declaran los elementos de un colección o array, estáis de enhorabuena ;) Porque, sin duda, hay formas de hacerlo menos verbosas que las que hemos tenido hasta ahora en C#:

// JavaScript:
let numbers = [1, 2, 3];

// Python:
numbers = [1, 2, 3]

// PHP:
$array = [1, 2, 3];

// Rust:
let array = [1, 2, 3];

En C# 11 y anteriores, la creación de un array es normalmente más farragosa, porque de alguna forma u otra requiere que especifiquemos que se trata de un nuevo array y, si la inferencia no lo permite, el tipo de los elementos que contendrá:

// Forma verbosa y redundante:
int[] arr1 = new int[3] { 1, 2, 3 };

// Forma clásica, usando 'var' y especificando número y tipo elementos:
var arr2 = new int[3] { 1, 2, 3 };

// Dejamos que el compilador detecte el número de elementos:
var arr3 = new int[] { 1, 2, 3 };

// Dejamos que la inferencia de tipos determine el tipo de los elementos:
var arr4 = new [] { 1, 2, 3 };

// O bien, la más concisa, usando la sintaxis con llaves (sólo válida para arrays):
int[] arr5 = { 1, 2, 3 };

lunes, 18 de diciembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 12 de diciembre de 2023
.NET

Los records son una interesante fórmula para definir tipos en C# de forma rápida gracias a su concisa sintaxis, además de ofrecer otras ventajas, entre las que destacan la inmutabilidad o la implementación automática de métodos como Equals(), GetHashCode() o ToString().

Por si no tenéis esto muy fresco, aquí va un ejemplo de record y la clase tradicional equivalente en C#:

// Record:
public record Person(string FirstName, string LastName);

// Clase equivalente (generada automáticamente):
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public override bool Equals(object obj)
    {
        return obj is Person person &&
               FirstName == person.FirstName &&
               LastName == person.LastName;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(FirstName, LastName);
    }

    public Person With(string FirstName = null, string LastName = null)
    {
        return new Person(FirstName ?? this.FirstName, LastName ?? this.LastName);
    }

    public void Deconstruct(out string firstName, out string lastName)
    {
        firstName = this.FirstName;
        lastName = this.LastName;
    }
}

Como podéis comprobar, hay pocas características de C# que ofrezcan una relación código/funcionalidad tan bárbara como los records. Por ello, poco a poco van ganando popularidad y comenzamos a verlos ya de forma habitual en código propio y ajeno.

Sin embargo, su concisa sintaxis hacen que a veces no sea fácil intuir cómo resolver algunos escenarios que, usando las clases tradicionales, serían triviales.

Por ejemplo, hoy vamos a centrarnos en un escenario muy concreto pero frecuente, cuya solución seguro que veis que puede ser aplicada en otros casos: ya que en los records no definimos propiedades de forma explícita, ¿cómo podríamos aplicarles atributos?

lunes, 11 de diciembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 4 de diciembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 28 de noviembre de 2023
Blazor

Como sabéis, hasta ahora, los componentes Blazor podían ejecutarse en dos tipos de hosting distintos, Blazor Server y Blazor WebAssembly. Aunque cada uno tiene sus escenarios ideales de uso, ambos enfoques conseguían lo mismo, implementar Single Page Applications en C#, sin necesidad de utilizar JavaScript (bueno, o al menos, minimizando radicalmente su uso):

  • Con Blazor Server, se mantiene en el servidor una copia del DOM de cada usuario conectado, de forma que C# puede manipularlo directamente. Luego, mediante una conexión websockets, se sincronizan los cambios con el cliente.
  • Blazor WebAssembly lleva al navegador el runtime de .NET, las bibliotecas base y los ensamblados de la aplicación, por lo que todo se ejecuta directamente en el lado cliente gracias a WebAssembly.

Estas dos formas de ejecutar componentes son muy apropiadas cuando se trata de elementos interactivos, capaces de responder a eventos de usuarios y con capacidad de actualizar el contenido de la página. Sin embargo, son muy poco eficientes cuando se trata de páginas estáticas que no requieren interacción con el usuario:

  • Para poder mostrar en el navegador un contenido, en Blazor Server hay que esperar a que el lado cliente descargue la página contenedora, un archivo JavaScript y se establezca la conexión websockets con el servidor, tras lo cual se enviará el contenido de la página.

  • En Blazor WebAssembly, el cliente debe descargar la página contenedora, los ensamblados y todo el entorno de ejecución de .NET y lanzarlo todo sobre WebAssembly. En este momento se puede mostrar el contenido de la página.

lunes, 27 de noviembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 20 de noviembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 14 de noviembre de 2023
C#

Desde su llegada con la versión 7 del lenguaje C#, allá por 2017, nuestro lenguaje favorito dispone de soporte para tuplas. Sin embargo, no he visto muchos proyectos donde estén siendo utilizadas de forma habitual; quizás sea porque pueden hacer el código menos legible, o quizás por desconocimiento, o simplemente porque lo que aportan podemos conseguirlo normalmente de otras formas y preferimos hacerlo como siempre para no sorprender al que venga detrás a tocar nuestro código.

Pero bueno, en cualquier caso, es innegable que las tuplas han venido para quedarse, así que en este post vamos a ver algunos usos posibles, y a veces curiosos, de esta característica del lenguaje C#.

lunes, 13 de noviembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 7 de noviembre de 2023
C#

El otro día me descubrí escribiendo un código parecido al siguiente:

return $"Order: {Items.Length} items, {Total.ToString("#,##0.#0")}";

Mal, lo que se dice mal, no estaba; funcionaba perfectamente y cumplía los requisitos, pero me di cuenta de que no estaba aprovechando todo el potencial de las cadenas interpoladas de C# que ya habíamos comentado por aquí mucho tiempo atrás.

Y como siempre que tengo algún despiste de este tipo, pienso que quizás pueda haber alguien más al que le ocurra o no esté al tanto de esta posibilidad el lenguaje, así que vamos a ver cómo podíamos haberlo implementado de forma algo más simple.

lunes, 6 de noviembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 30 de octubre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 24 de octubre de 2023
ASP.NET Core

Pues hoy vamos con un truquillo rápido ;)

Como sabemos, cuando usamos Razor Pages para construir aplicaciones sobre ASP.NET Core, la convención por defecto obliga a que nuestras páginas se encuentren en la carpeta /Pages del proyecto.

¿Pero qué ocurre si somos algo tiquismiquis y no nos gusta esa ubicación o no podemos usarla por cualquier motivo? En este post vamos a ver cómo cambiar esta convención para que nuestras páginas Razor se encuentren en otra carpeta.

lunes, 23 de octubre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 17 de octubre de 2023
.NET

Sabemos que está feo y no sea especialmente recomendable en muchos casos, pero hay veces en las que es totalmente necesario acceder a miembros privados de una clase. Por ejemplo, sería un requisito  imprescindible si fuéramos a implementar un serializador o deserializador personalizado, o necesitásemos clonar objetos, o simplemente realizar pruebas unitarias a una clase que no ha sido diseñada para ello.

Para conseguirlo, siempre hemos utilizado los mecanismos de introspección de .NET, conocidos por todos como reflexión o por su término en inglés reflection. Por ejemplo, imaginemos una clase como la siguiente, virtualmente inexpugnable:

public class BlackBox
{
    private string _message = "This is a private message";
    private void ShowMessage(string msg) => Console.WriteLine(msg);
    public override string ToString() => _message;
}

Aunque a priori no podemos hacer nada con ella desde fuera, usando reflexión podríamos acceder sin problema a sus miembros privados, ya sean propiedades, campos, métodos o cualquier tipo de elemento, como podemos ver en el siguiente ejemplo:

var instance = new BlackBox();

// Obtenemos el valor del campo privado _message:
var field = typeof(BlackBox)
    .GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance);
var value = field!.GetValue(instance);

// Ahora llamamos al método privado ShowMessage():
var method = typeof(BlackBox)
    .GetMethod("ShowMessage", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(instance, [value]);

// Al ejecutar, se nuestra en consola: "This is a private message"

Sin embargo, de todos es sabido que la reflexión es un mecanismo muy lento, a veces farragoso en su implementación y, sobre todo, incompatible con tree-shaking, que es como se suele llamar la técnica que usan los compiladores de eliminar del código final todas las clases, métodos y propiedades que no se utilizan en el código final. Esta técnica va tomando cada vez más relevancia conforme los compiladores son capaces de crear directamente ejecutables nativos puros, porque permiten reducir de forma considerable el peso de los artefactos creados.

Por esta razón, en .NET 8 se ha incluido una nueva fórmula para acceder a miembros privados, mucho más eficiente y amistosa con AOT, porque se lleva a tiempo de compilación algo que antes obligatoriamente se resolvía en tiempo de ejecución.

lunes, 16 de octubre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 9 de octubre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 2 de octubre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 26 de septiembre de 2023
.NET

Seguro que más de una vez habéis tenido que construir una abstracción sobre DateTime para poder controlar apropiadamente la obtención de la fecha/hora actual y otras operaciones relacionadas con el tiempo.

Suelen ser bastante útiles cuando creamos pruebas unitarias de métodos que dependan del momento actual. Por ejemplo, ¿cómo testearíamos de forma automática que las dos líneas de ejecución del siguiente método DoSomething() funcionan correctamente? Sería imposible salvo que ejecutásemos las pruebas a una hora determinada, algo que se antoja complicado 😉

public class MyClass
{
    public string DoSomething()
    {
        var now = DateTime.Now;
        return now.Second == 0
            ? "A new minute is starting"
            : "Current second " + now.Second;
    }
}  

Sin duda, una forma mejor y más test friendly sería contar con una abstracción sobre el proveedor de tiempos capaz de retornar la fecha y hora actual, por ejemplo:

public interface IDateTimeProvider
{
    DateTime GetCurrentDateTime();
}

De esta forma, podríamos reescribir la clase MyClass de forma que recibiera por inyección de dependencias nuestro proveedor IDateTimeProvider. Así sería realmente sencillo crear un par de pruebas unitarias que, suministrando los valores correctos a través de esta dependencia, podrían recrear los escenarios a cubrir:

public class MyClass
{
    private readonly IDateTimeServices _dateTimeServices;
    public TimeHelpers(IDateTimeServices dateTimeServices)
    {
        _dateTimeServices = dateTimeServices;
    }
    public string DoSomething()
    {
        var now = _dateTimeServices.GetCurrentDateTime();
        return now.Second == 0
            ? "A new minute is starting"
            : "Current second " + now.Second;
    }
}  

Aunque hacerlo de esta manera en nuestras aplicaciones es lo ideal, hay partes que se quedarían fuera de esta posibilidad, como las bibliotecas de terceros que de alguna forma dependan de las funcionalidades proporcionadas por DateTime.

Por esta razón, .NET 8 va a introducir una abstracción que nos permitirá gestionar estos escenarios de forma más homogénea y generalizada en aplicaciones y componentes .NET. 

Os presento la clase abstracta TimeProvider 😁

lunes, 25 de septiembre de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 18 de septiembre de 2023
Enlaces interesantes

La verdad es que este año me ha dado algo de pereza volver a abrir el blog después de este periodo veraniego de descanso. Aunque disfrute escribiendo y compartiendo información, mantener esto medio vivo requiere esfuerzo y tiempo, que obviamente dejo de dedicar a otras cosas que también me gustan 🙂

Pero bueno, la cuestión es que por aquí andamos de nuevo, listos para inaugurar oficialmente la temporada 2023-2024. ¿Y qué mejor forma de hacerlo que con una nueva recopilación de enlaces interesantes? ¡Pues vamos allá!

Por si te lo perdiste...

.NET Core / .NET

miércoles, 12 de julio de 2023
Playa de Costa Ballena

Si sois habituales del blog, probablemente ya sabréis lo que os voy a decir ;)

Como todos los años por estas fechas, empieza el periodo vacacional y aprovecharé para bajar un poco el ritmo, descansar unos días y disfrutar de familia y amigos. 

Por tanto, dejaré el blog en modo de bajo consumo hasta bien entrado septiembre, cuando, ya con las pilas recargadas, volveré al ataque con nuevos artículos y enlaces interesantes. Eso sí, durante este periodo seguiré echando el ojo periódicamente a comentarios o mensajes que me dejéis, aunque no los responderé con la misma celeridad que en otras épocas del año.

Aprovecho para desearos a todos un feliz verano y que disfrutéis de las vacaciones. ¡Nos vemos a la vuelta!

Publicado en Variable not found.

lunes, 10 de julio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

viernes, 7 de julio de 2023
MVP

Por decimotercer año consecutivo, me complace enormemente informaros de que Microsoft ha tenido a bien reconocerme de nuevo como MVP (Most Valuable Professional) en tecnologías de desarrollo. ¡13 años ya, uau! ¡Pero si el primero parece que fue ayer!

Muchas gracias al increíble equipo de Microsoft que hay detrás de este programa por haberme honrado con este reconocimiento, y especialmente a nuestra gran Cristina González por su dedicación, cercanía y ponérnoslo todo tan fácil cuando la necesitamos.

También agradeceros a vosotros, mis queridos amigos, que sois los que con vuestras visitas, lecturas, comentarios y apoyo incondicional hacéis que este sueño siga siendo posible año tras año.

¡Nos vemos por aquí!

Publicado en Variable not found.

martes, 4 de julio de 2023
.NET

Seguro que habéis visto más de una vez un código parecido al siguiente, en el que llamamos a una API  REST externa y su resultado es deserializado a un objeto .NET para introducirlo en el flujo de la aplicación:

async Task<User[]> GetUsersAsync()
{
    var httpClient = _httpClientFactory.CreateClient();
    
    // Hacemos la llamada
    var response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/users");

    // Si la cosa no fue bien, retornamos
    if (!response.IsSuccessStatusCode)
        return Array.Empty<User>();

    // Descargamos la respuesta y la deserializamos
    var usersAsJson = await response.Content.ReadAsStringAsync();
    var users = JsonSerializer.Deserialize<User[]>(usersAsJson);

    return users;
}

Fijaos que el JSON de la respuesta de la API lo guardamos en una cadena de caracteres para, justo después, deserializarlo y convertirlo en un array de objetos User. Que levante la mano el que no lo haya hecho nunca 😉

¿Y veis dónde está el problema? A la salida de este método, tendremos en memoria dos copias de los datos de los usuarios, una en forma de string JSON y otra en el objeto que hemos deserializado.

Si estamos hablando de respuestas pequeñas o con poca concurrencia, probablemente el impacto es inapreciable. Pero si las estructuras retornadas por la API tuvieran un tamaño considerable o estamos en un escenario de múltiples llamadas simultáneas, esta duplicidad sería un auténtico derroche de recursos.

lunes, 3 de julio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 27 de junio de 2023
ASP.NET Core

Cuando en ASP.NET Core MVC usamos rutado por convención, lo habitual es que accedamos a las acciones mediante rutas definidas en el patrón, como [controller]/[action]. Así, podemos encontrarnos con rutas como /PendingInvoices/ViewAll para acceder a la siguiente acción:

public class PendingInvoicesController : Controller
{
    public IActionResult ViewAll() => Content("Show all pending invoices");
}

Lo mismo ocurre con páginas Razor. Si usamos las rutas por defecto, al archivo /Pages/ShowAllPendingInvoices.cshtml podríamos acceder mediante la ruta /ShowAllPendingInvoices. No es que sean rutas terribles, pero tampoco podemos decir que sean lo mejor del mundo en términos de legibilidad y conveniencia.

El kebab-casing consiste en separar con un guion "-" las distintas palabras que componen los fragmentos de la ruta, por lo que en los casos anteriores tendríamos /pending-invoices/view-all y show-all-pending-invoices, algo bastante más legible, elegante, y apropiado desde el punto de vista del SEO.

El nombre kebab-casing viene de que visualmente el resultado es similar a un pincho atravesando trozos de comida. Imaginación que no falte 😉

En este post vamos a ver cómo aprovechar los puntos de extensibilidad del sistema de routing de ASP.NET Core para modificar la forma en que genera rutas y así adaptarlo a nuestras necesidades.

lunes, 26 de junio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 20 de junio de 2023
C#

Desde la aparición de los nullable reference types, o tipos referencia anulables, en C# 8, nos encontramos frecuentemente con el warning de compilación CS8618, que nos recuerda que las propiedades de tipo referencia definidas como no anulables (es decir, que no pueden contener nulos) deben ser inicializadas obligatoriamente porque de lo contrario contendrán el valor null, algo que iría en contra de su propia definición.

Para verlo con un ejemplo, consideremos una aplicación de consola con el siguiente código:

var friend = new Friend() {Name = "John", Age = 32};
Console.WriteLine($"Hello, {friend.Name}");

public class Friend
{
    public string Name { get; set; }
    public int Age { get; set; }
}

La aplicación se ejecutará sin problema, aunque al compilarla obtendremos el warning CS8618:

D:\Projects\ConsoleApp78>dotnet build
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored D:\Projects\ConsoleApp78\ConsoleApp78.csproj (in 80 ms).
D:\Projects\ConsoleApp78\Program.cs(8,19): warning CS8618: Non-nullable property 'Name' 
 must contain a non-null value when exiting constructor. Consider declaring the 
 property as nullable.
[...]

[D:\Projects\ConsoleApp78\ConsoleApp78.csproj]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.63

D:\Projects\ConsoleApp78\ConsoleApp78>_

También en Visual Studio podremos ver el subrayado marcando la propiedad como incorrecta:

Visual Studio mostrando el warning CS8618 sobre la propiedad

Aunque muchas veces este warning viene bien porque nos ayudará a evitar errores, hay otras ocasiones en las que puede llegar a ser molesta tanta insistencia. Y en estos casos, ¿cómo podemos librarnos de este aviso?

Disclaimer: algunas de las soluciones mostradas no son especialmente recomendables, o incluso no tienen sentido en la práctica, pero seguro que son útiles para ver características de uso poco habitual en C#.

lunes, 19 de junio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 13 de junio de 2023
C#

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 en Variable not found.
lunes, 12 de junio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 6 de junio de 2023
.NET

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.

lunes, 5 de junio de 2023
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET