Зачем нужны свойства get/set в C#, если есть обычные поля?
Не понимаю смысла свойств. Зачем писать { get; set; }, если можно просто сделать public-поле? В чём разница и что такое автосвойства?
public string Name; // поле
public string Name2 { get; set; } // свойство — в чём профит?
2 ответа
Свойство выглядит как поле, но на самом деле это пара методов (get и set), скрытая за удобным синтаксисом. Главный профит — контроль доступа и валидация без изменения внешнего кода.
Сравните. Голое поле ничего не контролирует:
public int Age; // можно присвоить -100, никто не помешает
Свойство с логикой:
class Person
{
private int age;
public int Age
{
get => age;
set
{
if (value < 0)
throw new ArgumentException("Возраст не может быть отрицательным");
age = value;
}
}
}
var p = new Person();
p.Age = 25; // ок
// p.Age = -5; // бросит исключение
Автосвойство — это сокращение, когда никакой особой логики пока не нужно. Компилятор сам создаёт скрытое поле:
public string Name { get; set; } // чтение и запись
public int Id { get; private set; } // менять только внутри класса
public string Country { get; } = "RU"; // только чтение, задаётся в конструкторе
Почему свойства, а не публичные поля: можно ограничить запись (private set), сделать только чтение, добавить валидацию или логирование позже — и при этом не сломать код, который уже использует obj.Name. С полем такой переход потребовал бы менять все обращения. Поэтому в C# принято: наружу — свойства, внутри — приватные поля.
Ещё пара полезных форм свойств.
Вычисляемое свойство только с get (хранилища нет, считается на лету):
class Rect
{
public double W { get; set; }
public double H { get; set; }
public double Area => W * H; // expression-bodied, только чтение
}
И init-свойства (C# 9) — можно задать только при создании объекта, потом неизменно:
class Point
{
public int X { get; init; }
public int Y { get; init; }
}
var p = new Point { X = 1, Y = 2 };
// p.X = 5; // ОШИБКА — после создания менять нельзя
Это удобно для неизменяемых (immutable) объектов.