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 ;)

19 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!
miércoles, 8 de mayo de 2024
¡Variable not found cumple 18 años Imagen generada con Copilot!

Buah, siempre se dice que el tiempo pasa volando, pero es que es verdad. Parece que fue ayer cuando decidí comenzar a escribir en este blog, y hoy hace 18 años de eso. ¡El blog ya es mayor de edad! 🎉

Cuando empecé a escribir por aquí, aún bajo el dominio de Blogger jmaguilar.blogspot.com y con un nombre ligeramente más largo (Variable not found, 0:1, como homenaje a mi querido ZX Spectrum), Windows XP aún llenaba de color las pantallas de nuestros vetustos PC, aunque empezábamos a oír hablar de un nuevo sistema operativo llamado Windows Vista.

Programábamos aplicaciones ASP.NET 2.0 en Visual Studio 2005, usando un C# que apenas acababa de incorporar el soporte para generics o tipos anulables, y las desplegábamos por FPT a hostings o servidores on-premise, porque las nubes eran simplemente algo con formas caprichosas que veíamos en el cielo.

Los teléfonos móviles no eran nada inteligentes, eso de los smartphones llegó más tarde. En aquellos tiempos estos dispositivos sólo servían para hacer llamadas y enviar SMS. A lo sumo, podíamos jugar al Snake, pero poco más. Nada que ver con los dispositivos que llevamos en el bolsillo en este momento, ni las herramientas que éstos han propiciado.

El código fuente de los proyectos lo guardábamos donde podíamos, muchas veces incluso sin usar sistema de gestión de código o control de versiones, o utilizando herramientas poco amigables (¿alguien tiene todavía pesadillas con Source Safe? 😉)

Internet era muy distinto. Aunque las ADSL ya habían llegado a muchos hogares, la velocidad de conexión era mucho menor que la que disfrutamos ahora. Servicios, que ahora son indispensables para nuestro trabajo, como Stack Overflow o GitHub aún no existían, como tampoco (o estaban muy en pañales) las redes y aplicaciones sociales que hoy en día nos mantienen informados y en contacto, como Twitter (creo que nunca me acostumbraré a llamarlo "X" 🤦‍♂️), Instagram, Facebook, WhatsApp, Youtube, Twitch o TikTok.

Y por supuesto, esto de la inteligencia artificial tal y como la estamos conociendo en este momento era absolutamente impensable. Los que no trabajábamos en ese campo, apenas empezábamos a oír hablar de cosas como el machine learning o redes neuronales, y no tenían aplicación en aplicaciones, digamos, "normales".

Las cosas han cambiado mucho desde entonces, pero una sigue igual: mi pasión por la tecnología y por compartir lo que voy aprendiendo siguen intactos. Por eso, aunque a veces cueste encontrar tiempo para escribir, sigo aquí, en este rincón de la red, compartiendo con vosotros lo que voy aprendiendo, lo que me parece interesante o lo que creo que puede ser útil para alguien.

Pero todos es gracias a vosotros, esa pequeña pero fiel pandilla de amigos que me lee, me comenta y me anima a seguir adelante. ¡Muchas gracias a todos!

Y como todos los años por estas fechas, vamos a hacer balance de cómo han ido las cosas en el blog, que ya os adelanto que regular 😔

lunes, 6 de mayo de 2024
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, 29 de abril de 2024
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, 23 de abril de 2024
C#

Cuando tenemos una colección de datos para procesar, es relativamente habitual tener que hacerlo por lotes, es decir, dividir la colección en partes más pequeñas e irlas procesando por separado.

Para ello, normalmente nos vemos obligados a trocear los datos en lotes o chunks de un tamaño determinado, y luego procesar cada uno de ellos.

Por ejemplo, imaginad que tenemos un método que recibe una lista de objetos a procesar y, por temas de rendimiento o lo que sea, sólo puede hacerlo de tres en tres. Si la lista de elementos a procesar es más larga de la cuenta, nos veremos previamente obligados a trocearla en lotes de tres para ir procesando cada uno de ellos por separado.

Tradicionalmente, es algo que hemos hecho de forma manual con un sencillo bucle for que recorre la lista completa, y va acumulando los elementos en un nuevo lote hasta que alcanza el tamaño deseado, momento en el que lo procesa y lo vacía para empezar de nuevo.

Pero otra posibilidad bastante práctica, y probablemente más legible, sería pasar la lista de elementos previamente por otro proceso que retorne una lista de chunks, o pequeñas porciones de la lista original, para que luego simplemente tengamos que ir procesándolos secuencialmente. Es decir, algo así:

private char[] array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
private int chunkSize = 3;

var chunks = GetChunks(array, chunkSize); // [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j']
foreach (var chunk in chunks) { ProcessChunk(chunk); // 'chunk' sería un array de 3 elementos }

Y la pregunta es, ¿cómo podríamos implementar ese método GetChunks() en C#? Vamos a ver varias opciones.

lunes, 22 de abril de 2024
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, 16 de abril de 2024
.NET

Hace poco vimos cómo serializar y deserializar datos en JSON de forma personalizada usando custom converters e implementamos un ejemplo simple capaz de introducir en campos de tipo int de .NET casi cualquier valor que pudiera venir en un JSON.

Pero como comentamos en su momento, la serialización y deserialización de objetos más complejos no es una tarea tan sencilla y requiere algo más de esfuerzo. En este post vamos a ver la solución para un escenario que creo que puede ser relativamente habitual: deserializar un objeto JSON a un diccionario Dictionary<string, object>.

En otras palabras, queremos que funcione algo como el siguiente código:

using static System.Console;
...
var json = """
{
    "name": "Juan",
    "age": 30
}
""";

var dict = ... // Código de deserialización
WriteLine($"{dict["name"]} tiene {dict["age"]} años"); // --> Juan tiene 30 años

lunes, 15 de abril de 2024
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, 9 de abril de 2024
Blazor

Este tema lo he debatido con colegas en varias ocasiones y creo que abordarlo aquí puede resultar interesante para algunos más que os estéis preguntando lo mismo a raíz de la tracción que, poco a poco, va tomando Blazor entre los desarrolladores web que trabajamos con el stack de tecnologías de Microsoft.

Voy a explicar mi punto de vista al respecto contemplando dos aspectos distintos, que creo que son los fundamentales para poder responder apropiadamente a esta pregunta:

  • Si técnicamente sería posible reemplazar MVC por Blazor, esto es, si Blazor dispone de mecanismos suficientes para cubrir las necesidades de una aplicación que tradicionalmente se desarrollaría con MVC.
  • Si la popularidad y difusión de Blazor podría llegar a alcanzar las cotas suficientes para convertirse en una alternativa completa y segura a MVC, en términos de madurez, estabilidad, soporte y tamaño de la comunidad. O en otras palabras, si Blazor como producto llegará a estar lo suficientemente consolidado como para poder reemplazar a MVC.

Vamos a analizar cada una de ellas.

Disclaimer: obviamente, todo lo que veréis a continuación son opiniones personales y, como tales, pueden ser discutibles. Si tenéis una opinión diferente, estaré encantado de leerla en los comentarios.

lunes, 8 de abril de 2024
Enlaces interesantes

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

Por si te lo perdiste...

.NET Core / .NET

miércoles, 3 de abril de 2024
C#

Hoy va un post rápido sobre una característica de C# 12 que, aunque pequeña, nos puede resultar interesante en determinadas situaciones y puede pasar fácilmente desapercibida entre todas las demás novedades de esta versión del lenguaje.

Hasta C# 11 (.NET 7), no teníamos forma de definir una expresión lambda con parámetros opcionales y valores por defecto, como podemos hacer en los métodos o funciones normales, lo que complicaba la implementación de algunos escenarios.

martes, 2 de abril de 2024
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, 25 de marzo de 2024
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, 19 de marzo de 2024
Blazor
Update 13/06/2025: si usas Blazor 9 o superior, hay fórmulas mejores de determinar el modo de renderización de un componente Blazor.

Como sabéis, con ASP.NET Core 8 se ha incluido la posibilidad de que una página Blazor sea capaz de procesar directamente una petición HTTP, renderizando sus componentes y retornando el resultado HTML completo al lado cliente de forma estática. Es ya lo vimos hace algún tiempo cuando hablamos de Server-Side Rendering (SSR), una de las piezas clave para conseguir que Blazor sea un framework fullstack.

En la práctica, esta opción posibilita la implementación de sitios estáticos completos, como los que construiríamos con ASP.NET Core MVC, Razor Pages o cualquier otro tipo de tecnología de servidor, pero con la gran ventaja de que en este caso estaremos beneficiándonos del fantástico modelo de componentes Blazor, que es una gozada en términos de productividad y facilidad de uso, y sin perder la posibilidad de activar la interactividad de los componentes (su capacidad para reaccionar ante eventos del usuario), una vez que el HTML ha sido descargado en el navegador.

En aquél momento vimos que SSR no requiere una programación específica: los mismos componentes interactivos que luego podemos ejecutar en el lado cliente o servidor pueden ser renderizados mediante SSR de forma estática en el backend. Sin embargo, en algunos momentos nos podría resultar interesante saber si un componente está funcionando en modo estático (SSR) o interactivo (los tradicionales Blazor WebAssembly o Blazor Server).

lunes, 18 de marzo de 2024
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 marzo de 2024
Blazor

Los que llevamos muchos años programando con ASP.NET/ASP.NET Core y todos los frameworks que han ido surgiendo en su ecosistema, estamos familiarizados con el concepto de "contexto HTTP".

Materializado en forma de objeto de tipo HttpContext, el contexto HTTP es una de las piezas fundamentales de la infraestructura de ASP.NET Core, y nos permite acceder a información sobre la petición HTTP que se está procesando, como los encabezados, el cuerpo de la petición, las cookies, etc., así como base para la generación de la propia respuesta a través de su propiedad Response. En muchos escenarios, se trata de un recurso imprescindible para procesar la petición de la forma adecuada, por lo que estamos acostumbrados a usarlo cuando es conveniente.

Sin embargo, cuando saltamos a Blazor, pronto nos llama la atención que HttpContext no está disponible. Y si lo pensamos, esto tiene bastante sentido en los dos modos de renderización clásicos:

  • En Blazor WebAssembly, dado que el código .NET se ejecuta directamente en el cliente, no existen peticiones que procesar y, por tanto, no existe HttpContext. Se trata de una abstracción que sólo existe en el backend.

  • En Blazor Server, aunque el código se está ejecutando en el servidor, tampoco tenemos disponible HttpContext porque realmente no existen peticiones: el lado cliente y servidor se comunican mediante un canal websockets implementado con SignalR, que es por donde viajan ascendentemente las acciones realizadas por el usuario y descendentemente las actualizaciones del DOM de la página.

Con la llegada de Blazor 8, ha tomado relevancia el nuevo modo de renderizado, llamado Server-Side Rendering (SSR) o renderización en el lado servidor, que ya vimos por aquí hace algún tiempo.

Como ya sabemos, el funcionamiento de Blazor SSR es similar al de otros frameworks de backend puros, como MVC o Razor Pages: el servidor recibe la petición, la procesa y genera una respuesta HTML que se envía al cliente. En este escenario, durante el proceso del componente Blazor sí existe un contexto HTTP.

lunes, 11 de marzo de 2024
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, 5 de marzo de 2024
Blazor

En Blazor es posible acceder a valores de parámetros de la query string exclusivamente desde componentes de tipo página, es decir, aquellos definidos con la directiva @page.

Para ello, bastaba con declarar una propiedad pública y decorarla con los atributos [Parameter] y [SupplyParameterFromQuery]. Por ejemplo, si desde una página quisiésemos obtener el valor del parámetro term de la query string, podríamos hacerlo de la siguiente forma:


@page "/search"

<p>Searching term: @Term</p>

@code {

    [Parameter]
    [SupplyParameterFromQuery]
    public string Term { get; set; }
}

Sin embargo, como sabéis, esto no funcionaba si intentábamos acceder así a estos parámetros desde componentes que no fueran páginas, es decir, que no fueran instanciados por el sistema de routing.

lunes, 4 de marzo de 2024
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, 26 de febrero de 2024
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 febrero de 2024
.NET

Hace poco, andaba enfrascado en el proceso de modernización de una aplicación antigua que, entre otras cosas, guardaba datos en formato JSON en un repositorio de archivos. Dado que se trataba de una aplicación creada con .NET "clásico", la serialización y deserialización de estos datos se realizaba utilizando la popular biblioteca Newtonsoft.Json.

Al pasar a versiones modernas de .NET, esta biblioteca ya no es la mejor opción, pues ya el propio framework nos facilita las herramientas necesarias para realizar estas tareas de forma más eficiente mediante los componentes del espacio de nombres System.Text.Json. Y aquí es donde empiezan a explotar las cosas 😉.

Si habéis trabajado con este tipo de asuntos, probablemente habréis notado que, por defecto, los componentes de deserialización creados por James Newton-King son bastante permisivos y dejan pasar cosas que System.Text.Json no permite. Por ejemplo, si tenemos una clase .NET con una propiedad de tipo string y queremos deserializar un valor JSON numérico sobre ella, Newtonsoft.Json lo hará sin problemas, pero System.Text.Json nos lanzará una excepción. Esa laxitud de Newtonsoft.Json es algo que en ocasiones nos puede venir bien, pero en otras puede puede hacer pasar por alto errores en nuestros datos que luego, al ser procesados por componentes de deserialización distintos, podrían ocasionar problemas.

Por ejemplo, observad el siguiente código:

var json = """
           {
              "Count": "1234"
           }
           """;

// Deserializamos usando Newtonsoft.Json:
var nsj = Newtonsoft.Json.JsonConvert.DeserializeObject<Data>(json);
Console.WriteLine("Newtonsoft: " + nsj.Count);

// Intentamos deserializar usando System.Text.Json
// y se lanzará una excepción:
var stj = System.Text.Json.JsonSerializer.Deserialize<Data>(json);
Console.WriteLine("System.Text.Json: " + stj.Count);
Console.Read();

// La clase de datos utilizada
record Data(int Count);

Para casos como este, nos vendrá bien conocer qué son los custom converters y cómo podemos utilizarlos.

lunes, 19 de febrero de 2024
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 febrero de 2024
Blazor

Como seguramente sabréis, Blazor es la gran apuesta de Microsoft para el desarrollo de aplicaciones web con .NET. Sólo hay que ver la cantidad de novedades que han introducido en la última versión para darse cuenta de que están poniendo toda la carne en el asador y, de alguna forma, está convirtiéndose en la opción preferida para el desarrollo de este tipo de aplicaciones.

Pues bien, es un placer anunciaros que, tras varios meses de preparación, hace unos días hemos puesto en marcha el nuevo curso de desarrollo de aplicaciones Web con Blazor en .NET 8, como siempre, en CampusMVP.

Ha sido un trabajo duro, porque esta última versión ha venida cargada de novedades (sobre todo en lo relativo al nuevo modelo unificado propuesto por las Blazor Web Apps) y hemos tenido que revisar en profundidad y reescribir parte del contenido del curso, rehacer ejemplos y regrabar material audiovisual, todo con el objetivo de seguir siendo el mejor y más completo curso de Blazor del mercado.

En este post voy a intentar responder a las siguientes preguntas:

lunes, 12 de febrero de 2024
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 febrero de 2024
C#

Hace unos días, veíamos por aquí los constructores primarios de C#, una característica recientemente introducida en el lenguaje que permite omitir el constructor si en éste lo único que hacemos es asignar los valores de sus parámetros a campos de la clase.

Veamos un ejemplo a modo de recordatorio rápido:

// Clase con constructor tradicional
public class Person
{
    private readonly string _name;
    public Person(string name)
    {
        _name = name;
    }
    public override string ToString() => _name;
}

// La misma clase usando el constructor primario:
public class Person(string name)
{
    public override string ToString() => name;
}

Como comentamos en el post, los parámetros del constructor primarios eran internamente convertidos en campos privados de la clase, generados automáticamente e inaccesibles desde el código.

lunes, 5 de febrero de 2024
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, 30 de enero de 2024
C#

Hace ya algunos años, con la llegada de C# 9, los records nos mostraron otra forma de crear objetos distinta a los clásicos constructores. Ya entonces, y únicamente en aquél ámbito, se comenzó a hablar de primary constructors, pero no ha sido hasta C# 12 cuando se ha implementado de forma completa esta característica en el lenguaje.

En este post vamos a ver de qué se trata, cómo podemos utilizarlos y peculiaridades que hay que tener en cuenta.

lunes, 29 de enero de 2024
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, 23 de enero de 2024
Blazor

Como sabemos, gran parte de las validaciones en formularios Blazor las implementamos usando anotaciones de datos, o data annotations. Estas anotaciones nos permiten validar los datos de entrada antes de que ejecutemos la lógica de negocio, que normalmente se encontrará en el handler del evento OnValidSubmit del formulario.

Vemos un ejemplo de formulario Blazor aquí, y el código C# justo debajo:

@page "/friend"
<h3>FriendEditor</h3>

<EditForm Model="Friend" OnValidSubmit="Save">
    <DataAnnotationsValidator />
    <div class="form-group mb-2">
        <label for="name">Name:</label>
        <ValidationMessage For="()=>Friend.Name" />
        <InputText @bind-Value="Friend.Name" class="form-control" id="name" />
    </div>
    <div class="form-group mb-2">
        <label for="score">Score:</label>
        <ValidationMessage For="()=>Friend.Score" />
        <InputNumber @bind-Value="Friend.Score" class="form-control" id="score" />
    </div>
    <div class="form-group mb-2">
        <label for="birthDate">BirthDate:</label>
        <ValidationMessage For="()=>Friend.BirthDate" />
        <InputDate @bind-Value="Friend.BirthDate" class="form-control" id="birthDate" />
    </div>
    <div class="form-group mb-2">
        <button type="submit" class="btn btn-primary">Save</button>
    </div>
</EditForm>
@code {
    private FriendViewModel Friend = new();

    private async Task Save()
    {
        await Task.Delay(1000);
        Friend = new FriendViewModel();
    }

    public class FriendViewModel
    {
        [Required(ErrorMessage = "El nombre es obligatorio")]
        public string Name { get; set; }
        [Range(0, 10, ErrorMessage = "La puntuación debe estar entre {1} y {2}")]
        public int Score { get; set; }
        public DateTime BirthDate { get; set; }
    }
}

lunes, 22 de enero de 2024
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, 16 de enero de 2024
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, 15 de enero de 2024
Top posts 2023 en Variable not found

Primero, espero que hayáis disfrutado las fiestas y que el 2024 que acabamos de estrenar venga bien cargado de cosas buenas 🙂

Y para inaugurar el año, como cada primer post de enero, aprovecharemos para revisar las diez publicaciones más leídas durante los últimos 365 días.

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