junio 9, 2020

Desde el año 2000 han sido muchas las modificaciones y mejoras en el lenguaje, a veces cuesta acostumbrarse a estas nuevas funcionalidades, veamos que nos depara 20 años después:

Es posible declarar el valor de propiedades en el momento de creación de un objeto, no es posible modificar a posteriori estos valores.

1
2
3
4
5
public class Vehiculo
{
    public string Marca { get; init; }
    public string Modelo { get; init; }
}

Por tanto, si todas las propiedades de un objeto con valores primitivos (int, double…) son de solo lectura (inmutables), nos acercamos a la definición de estructura (struct). Recordemos que las estructuras contienen valores y las clases referencias a valores, el ejemplo básico:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Vehiculo
    public int Potencia; 
    public Vehiculo(int pot) 
    
        this.Potencia = pot; 
    
 
Vehiculo a = new Vehiculo(120); 
Vehiculo b = a; 
a.Potencia = 200; 
 
System.Console.WriteLine(b.Potencia);

El resultado que se muestra siendo una estructura es de 120, si definimos como clase se mostraría 200. [que recuerdos de punteros ;)]

Volvamos a las novedades teniendo claras las diferencias, podemos utilizar la declaración data para las clases, aunque realmente estaremos hablando de solo DATOS:

1
2
3
4
5
public data class Vehiculo
{
    public string Marca { get; init; }
    public string Modelo { get; init; }
}

Pero podremos definirlos de manera rápida y equivalente:

1
public data class Vehiculo { string Marca; string Modelo}

Tampoco parece un gran avance… pero se añaden más características. Podemos realizar una copia del datos modificando solo una parte de manera rápida:

1
2
3
4
5
6
7
var vehiculo1 = new Vehiculo
{
    Marca = "Honda",
    Modelo = "Civic"
};
 
var vehiculo2 = vehiculo1 with { Modelo = "NSX" };

Existe un constructor por defecto que permite realizar una copia de todas las propiedades.

1
protected Vehiculo(Vehiculo original)

El comportamiento por defecto, cuando comparamos objetos que han sido modificados/copiados puede llegar a la situación en la que sean objectos diferentes pero el contenido sea el mismo, siguiendo con el ejemplo modificamos de nuevo la propiedad:

1
2
3
4
var vehiculo3 = vehiculo2 with { Modelo = "Civic" };
 
Equals(vehiculo3, vehiculo1); // TRUE
ReferenceEquals(vehiculo3, vehiculo1); // FALSE

Vamos a añadir herencia para acercarnos a escenarios reales:

1
2
3
4
5
public data class Vehiculo { string Marca; string Modelo}
public data class Coche : Vehiculo { string Matricula}
 
Vehiculo v1 = new Vehiculo {Marca = "Honda, Modelo = "Civic"}
Vehiculo v2 = new Coche {Marca = "Honda, Modelo = "Civic", Matricual = "0000LGS"}

En este caso, si comparamos v1 con v2 ¿serán iguales? C# utiliza una propiedad virtual protegida llamada «EqualityContract«, cada registro derivado lo anula por lo que para poder comprar los dos objetos deben tener el mismo «EqualityContract«

Basado en las notas de Mads Togersen