Cargando...

Tipos Record y Objetos Inmutables en C#

Aprende record types y objetos inmutables en C#, incluyendo igualdad por valor, expresiones with y ejemplos prácticos.

Introducidos con C# 9, los tipos record facilitan la creación de objetos inmutables (no modificables). Los records, al igual que las clases, pueden contener tanto datos como comportamiento; sin embargo, su propósito principal es definir objetos de datos (modelos de datos, DTO, etc.) de una manera más simple, segura y legible. Los objetos inmutables son aquellos cuyos valores no pueden cambiar después de su creación. Este enfoque mejora la seguridad en escenarios multi-hilo (multi-threading) y reduce el riesgo de errores.


¿Qué es un Record?

La palabra clave record se utiliza para definir tipos de datos similares a clases o estructuras. De forma predeterminada, los records proporcionan igualdad basada en valores (value-based equality). Es decir, si los campos de dos objetos record son iguales, los objetos se consideran iguales.


public record Person(string Name, int Age);

class Program
{
    static void Main()
    {
        var p1 = new Person("Juan", 30);
        var p2 = new Person("Juan", 30);

        Console.WriteLine(p1 == p2); // True (comparación basada en valores)
    }
}

Propiedades Inmutables

En los tipos record, las propiedades pueden definirse con el accesor init de forma predeterminada. Esto permite asignar valores al crear el objeto, pero impide modificarlos después.


public record Product
{
    public string Name { get; init; } = string.Empty;
    public decimal Price { get; init; }
}

class Program
{
    static void Main()
    {
        var p = new Product { Name = "Bolígrafo", Price = 12.5m };
        Console.WriteLine($"{p.Name} - {p.Price} EUR");

        // p.Price = 15m; // Error de compilación (propiedad init-only)
    }
}

La expresión with

Con los tipos record, la expresión with se puede usar para crear una copia de un objeto existente modificando solo los campos deseados. Esto es muy útil al trabajar con objetos inmutables.


var p1 = new Product { Name = "Cuaderno", Price = 45m };

// Crear una copia con la expresión with y cambiar el precio
var p2 = p1 with { Price = 40m };

Console.WriteLine(p1.Price); // 45
Console.WriteLine(p2.Price); // 40

Record Class vs. Record Struct

Con C# 10 se añadió soporte para record struct. Esto significa que un record puede definirse no solo como un tipo basado en clase, sino también como un tipo valor. record class es un tipo de referencia, mientras que record struct es un tipo de valor.


public record struct Point(int X, int Y);

class Program
{
    static void Main()
    {
        var a = new Point(1, 2);
        var b = new Point(1, 2);

        Console.WriteLine(a == b); // True (igualdad basada en valores)
    }
}

Ventajas de los Objetos Inmutables


Ejemplo: Modelo de Datos Inmutable

En el siguiente ejemplo, el objeto Order se define como inmutable y se crean nuevas versiones usando la expresión with.


public record Order(int Id, string Customer, decimal Amount);

class Program
{
    static void Main()
    {
        var o1 = new Order(1, "Juan", 500m);
        Console.WriteLine(o1);

        // Crear una copia con la expresión with
        var o2 = o1 with { Amount = 600m };
        Console.WriteLine(o2);
    }
}
// Salida:
Order { Id = 1, Customer = Juan, Amount = 500 }
Order { Id = 1, Customer = Juan, Amount = 600 }

TL;DR

  • record: Nuevo tipo que proporciona igualdad basada en valores.
  • Propiedades init: Se asignan al crear el objeto, no se pueden modificar después.
  • Expresión with: Usada para derivar copias de objetos inmutables.
  • record class = tipo de referencia, record struct = tipo de valor.
  • Los objetos inmutables son seguros en múltiples hilos, fiables y ofrecen un modelo más legible.

Artículos relacionados