1. Propiedades automáticas
En C#, las propiedades (property) son algo entre un campo y un método. Básicamente, es azúcar sintáctico que hace que trabajar con la encapsulación sea súper cómodo. Accedes a la propiedad como si fuera un campo normal, pero por dentro puede haber cualquier lógica: validación de datos, cambiar otros campos, llamar métodos e incluso mandar un e-mail a tu abuela (esto último, mejor no lo hagas). En la lección anterior escribíamos las propiedades a mano. Pero eso cansa rápido si tienes 100500 objetos simples donde solo necesitas un "getter" y un "setter" — sin lógica especial.
Aquí llegan las propiedades automáticas. Te salvan del código repetitivo y dejan que C# se encargue de guardar el valor por ti.
Cómo era antes: propiedades manuales
Cuando quieres ocultar un campo pero dar acceso a través de una propiedad, normalmente escribes algo así:
public class Dog
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
Este tipo de código es el típico "rollo" (boilerplate). Y muchas veces no necesitas añadir nada a esos get/set. Solo quieres acceso — y ya.
Cómo se puede ahora
En C# todo es más fácil: ya no tienes que escribir los campos a mano — el compilador lo hace por ti. Solo tienes que poner:
public class Dog
{
public string Name { get; set; }
}
Y listo. Puedes leer y cambiar el valor de Name tranquilamente, y por debajo el compilador crea un campo privado que no puedes tocar directamente desde fuera.
¿Qué pasa realmente detrás de cámaras? Cuando en el código aparece public string Name { get; set; }, el compilador crea automáticamente un campo oculto tipo Name__BackingField. Cada vez que accedes a Name, mete el getter o setter necesario. El campo no se ve en el código, pero existe — y con reflexión incluso puedes encontrarlo (pero eso ya es otra historia).
¿Por qué mola este enfoque? Primero, es mucho más corto y no tienes que repetir lo mismo. Segundo, el código es más limpio: menos ruido visual, más fácil de leer y mantener. Y por último, es más seguro — nadie puede toquetear los campos directamente, el acceso es solo por las propiedades.
2. Sintaxis de propiedades automáticas
La sintaxis es súper simple:
public class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
¡Ahora nuestro Dog se ve mucho más limpio! Podemos crear objetos y poner valores como siempre:
Dog myDog = new Dog();
myDog.Name = "Rex";
myDog.Age = 4;
Esquemáticamente
| Método | Sintaxis | Acceso al valor |
|---|---|---|
| Campo | |
Acceso directo |
| Propiedad manual | |
Acceso por get/set |
| Propiedad automática | |
get/set + campo oculto |
3. Personalización de acceso: solo lectura, solo escritura
Solo lectura: get-only
Si solo necesitas leer una propiedad (por ejemplo, el código de registro de la mascota), puedes hacerla solo de lectura — poniendo get y sin set, o haciendo el set privado. Ese valor solo se puede asignar en el constructor o directamente al declararlo:
public class Dog
{
public string RegistrationCode { get; }
public Dog()
{
RegistrationCode = "DOG-001"; // Asignamos valor en el constructor
}
}
Ahora desde fuera solo puedes leer RegistrationCode, pero no cambiarlo. Es una forma genial de proteger datos importantes de cambios accidentales.
Otra opción: set privado
public string Name { get; private set; }
Así, la propiedad solo se puede cambiar dentro de la clase (por ejemplo, en un método o en el constructor).
Solo escritura: mala idea
Teóricamente puedes hacer una propiedad set-only (solo escritura), pero es muy raro y no se recomienda — imagina un objeto que es como un "agujero negro": puedes tirar cosas dentro, pero nunca recuperarlas.
4. Setters init-only
Un poco de historia
Antes, para hacer un objeto inmutable (immutable), tenías que escribir solo propiedades get y poner los valores en el constructor. OK, está bien — pero no siempre es cómodo. Pero hace poco en C# apareció una nueva sintaxis: propiedades init-only.
¿Qué tiene de especial el setter init?
- Permite asignar el valor de la propiedad solo al crear el objeto (o sea en el constructor o en el inicializador de objeto).
- Después de crear el objeto, la propiedad es solo de lectura.
- Perfecto para clases "casi inmutables", DTO, configuraciones, modelos.
public class Dog
{
public string Name { get; init; }
public int Age { get; init; }
}
Ahora podemos hacer esto:
Dog dog = new Dog { Name = "Bobik", Age = 2 };
dog.Name = "Rex"; // ¡Error! Después de crear - solo lectura
En el constructor también puedes asignar valores:
public Dog(string name, int age)
{
Name = name;
Age = age;
}
Esquema: ¿cuándo se puede asignar?
| ¿Dónde asignar? | { get; set; } | { get; private set; } | { get; init; } |
|---|---|---|---|
| Fuera de la clase, después de crear | ✅ | ❌ | ❌ |
| En el constructor | ✅ | ✅ | ✅ |
| En el inicializador | ✅ | ❌ | ✅ |
| Dentro de la clase | ✅ | ✅ | ❌ (excepto en el constructor) |
5. Uso en la práctica
Vamos a reescribir nuestra clase Dog usando propiedades automáticas y solo-init:
public class Dog
{
// Propiedad, solo se puede asignar al inicializar
public string Name { get; init; }
public int Age { get; init; }
// Propiedad automática para el estado actual
public bool IsHungry { get; set; }
// Método, acciones del perro
public void Bark()
{
Console.WriteLine($"{Name} dice: ¡Guau!");
}
}
Ahora podemos crear Dog así:
Dog dog = new Dog { Name = "Scooby", Age = 3, IsHungry = true };
dog.Bark(); // mostrará: Scooby dice: ¡Guau!
dog.IsHungry = false; // esta propiedad se puede cambiar después de crear
dog.Name = "Rex"; // ¡Error! Propiedad solo para inicialización
6. Propiedades automáticas con valores iniciales
En C# todo está pensado para tu comodidad. Incluso puedes poner un valor inicial a la propiedad:
public class Dog
{
public string Name { get; set; } = "SinNombre";
public int Age { get; set; } = 0;
}
O con init:
public class Dog
{
public string Name { get; init; } = "Cachorro";
public int Age { get; init; } = 0;
}
Ahora si no pones Name al crear, será "Cachorro".
7. Propiedades automáticas con diferentes niveles de acceso
Puedes hacer que la propiedad se lea y escriba con diferentes modificadores de acceso:
public class Dog
{
public string Name { get; private set; }
public int Age { get; private set; }
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
En este caso, solo puedes cambiar el nombre y la edad dentro de la clase Dog, por ejemplo, en métodos o en el constructor.
Comparación de propiedades manuales y automáticas
| Enfoque | Dificultad de escribir | Control en set/get | Cambiable después de crear | Uso en modelos |
|---|---|---|---|---|
| Propiedad manual | Largo | Absoluto | Cualquiera | Donde hace falta lógica |
| Propiedad automática | Corto | No | Cualquiera o privado | Casi siempre |
| Automática init-only | Corto | No | Solo al crear | DTO, configs |
8. Errores típicos al trabajar con propiedades
Error nº1: intentar asignar valor a una propiedad get-only fuera del constructor.
Si la propiedad solo tiene get, el compilador no te dejará cambiar su valor en otro sitio. Solo puedes asignar en el constructor o al declararla. Si se te olvida — error de compilación.
Error nº2: confundir campo y propiedad.
Cuando cambias un campo normal por una propiedad automática, asegúrate de que en el resto del código no haya accesos directos al campo. Campo y propiedad son cosas distintas, y si dejas los accesos antiguos, el compilador dará error o el programa se comportará raro.
Error nº3: set privado sin entender las consecuencias.
Si la propiedad tiene un set privado, pero en el resto del código intentas asignarle valores — error. Esto pasa mucho por accidente, sobre todo copiando código de otros. Siempre revisa si el set está accesible donde lo vas a usar.
GO TO FULL VERSION