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

17 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, 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?

Por ejemplo, en el siguiente código definimos un record, creamos una instancia del mismo y mostramos su serialización en JSON por consola:

var p = new Person("John Smith", "jsmith@server.com");
Console.WriteLine(JsonSerializer.Serialize(p));
// Muestra: {"Name":"John Smith","Email":"jsmith@server.com"}

public record Person(string Name, string Email);

Pero imaginad que queremos ignorar la propiedad Email y que la propiedad Name aparezca como fullName. Normalmente usaríamos atributos como [JsonIgnore] o [JsonPropertyName("fullName")] sobre las propiedades para conseguirlo, pero como en este caso no las tenemos disponibles, debemos hacerlo así:

public record Person([property: JsonPropertyName("fullName")] string Name, 
                     [property: JsonIgnore] string Email);

Observad que no se trata de aplicar directamente los atributos [JsonIgnore], porque entonces los estaríamos usando contra los parámetros del constructor del record. Debemos incluir el prefijo property: para indicar que los atributos deben ser aplicados a las propiedades generadas automáticamente a partir de ellos.

De esta forma, si volvemos a ejecutar el código, veremos que ahora la propiedad Email no aparece en la serialización y la propiedad Name aparece como fullName:

var p = new Person("John Smith", "jsmith@server.com");
Console.WriteLine(JsonSerializer.Serialize(p));
// Muestra: {"fullName":"John Smith"}

public record Person([property: JsonPropertyName("fullName")] string Name, 
                     [property: JsonIgnore] string Email);

Como decía más arriba, aunque el ejemplo hayamos visto cómo aplicar atributos de serialización o deserialización, en realidad podríamos hacer lo mismo con cualquier otro tipo de atributo que en condiciones normales aplicaríamos a las propiedades de una clase.

¡Espero que os sea de utilidad! 😊

Publicado en: www.variablenotfound.com.

Aún no hay comentarios, ¡sé el primero!