C# 8.0 – Specification – Readonly Members
Índice general – C# 8.0 – Specification
Otra de las características añadidas a C# 8.0 es la que denomina como Readonly Members.
El objetivo principal de esta característica es la de evitar errores dentro de la lógica de nuestras aplicaciones y estructuras.
Podremos indicar los miembros de una estructura como de sólo lectura generándose un aviso o warning en el caso de que usemos miembros que no están declarados como de sólo lectura.
Supongamos la siguiente estructura de ejemplo:
public struct PersonStruct { private string _name; public string Name { get => _name; } public int Age; public PersonStruct(string name, int age) { _name = name; Age = age; } public string GetPerson() { _name = Name.ToUpper(); return $"{Name} is {Age} years old"; } public readonly override string ToString() => $"{Name} is {Age} years old"; }
En este código, he declarado una propiedad Name de sólo lectura, y una variable Age pública (lectura/escritura).
El constructor de la estructura recibe dos parámetros correspondientes a la propiedad y variable anteriormente comentadas.
Un método GetPerson construirá un texto de salida, y la sobreescritura del método ToString se declara como readonly.
En tiempo de desarrollo y en compilación veremos un warning o aviso respecto a Name dentro de ToString.
El aviso indica lo siguiente:
Call to non-readonly member ‘Program.PersonStruct.Name.get’ from a ‘readonly’ member results in an implicit copy of ‘this’.
Es decir, llamar a un miembro no readonly desde un miembro readonly, da como resultado una copia implícita de this, lo cuál no es eficiente.
En este caso, declarando la propiedad de sólo lectura se resolverá el warning.
Algo parecido a lo siguiente:
public readonly string Name { get => _name; }
Ahora bien, modifiquemos levemente el ejemplo anterior aplicando la resolución al problema del warning y declarando como readonly a GetPerson.
El código quedará entonces de la siguiente forma:
public struct PersonStruct { private string _name; public readonly string Name { get => _name; } public int Age; public PersonStruct(string name, int age) { _name = name; Age = age; } public readonly string GetPerson() { _name = Name.ToUpper(); return $"{Name} is {Age} years old"; } public readonly override string ToString() => $"{Name} is {Age} years old"; }
Aquí no recibiremos un warning, sino un error.
Lo que hemos hecho aquí es declarar el método GetPerson como readonly, y dentro del código, hemos querido modificar la variable _name.
_name no está declarada como readonly, pero dentro del método readonly estamos tratando de modificar su valor, algo que estaría fuera del contexto de los permisos del propio método declarado como readonly, y como consecuencia, genera el siguiente error:
Cannot assign to ‘_name’ because it is read-only
Como anotación añadida debo indicar que sino hubiéramos declarado aquí la propiedad Name como readonly, Name dentro del método GetPerson declarado como readonly devolverá el mismo warning que veíamos anteriormente.
Dicho de otro modo, Readonly Members nos va a ayudar bastante a la hora de codificar nuestras estructuras y olvidar máximas a cumplir con respecto a la inmutabilidad de miembros y sus posibles riesgos.
Happy Coding!