Во многих типах определяется информация состояния, которую можно прочитать или изменить. Часто эта информация состояния реализуется полями типа. Вот, например, определение типа с двумя полями:
public sealed class Employee {
public String Name; // Имя сотрудника
public Int32 Age; // Возраст сотрудника
}
Такой код писать можно, но он в корне противоречит инкапсуляции. В данном случае к полям класса Employee можно получить доступ из любой части кода, а это значит, что и изменить их достаточно просто, а особенно - внести некорректные значения. К примеру, присвоив полю Age значение -5.
Поля надо скрывать, и делать это грамотно: использовать модификаторы доступа по назначению.
Используя свойства, код выше можно переписать так:
public sealed class Employee {
private String m_Name;
private Int32 m_Age;
public String Name {
get { return(m_Name); }
set { m_Name = value; } // Ключевое слово value
} // идентифицирует новое значение
public Int32 Age {
get { return(m_Age); }
set {
if (value < 0) // Ключевое слово value всегда
// идентифицирует новое значение
throw new ArgumentOutOfRangeException("value", value.ToString(),
"The value must be greater than or equal to 0");
m_Age = value;
}
}
}
Можно считать свойства «умными» полями, то есть полями с дополнительной логикой. CLR поддерживает статические, экземплярные, абстрактные и виртуальные свойства. Кроме того, свойства могут помечаться модификатором доступа и определяться в интерфейсах
Определяя свойство, обычно описывают пару методов: get и set. Однако опустив метод set, можно определить свойство, доступное только для чтения, а опуская только метод get, мы получим свойство, доступное только для записи. Методы get и set свойства довольно часто манипулируют закрытым полем, определенным в типе. Это поле обычно называют резервным (backing field). Однако методам get и set не приходится обращаться к резервному полю. Например, тип System.Threading.Thread поддерживает свойство Priority, взаимодействующее непосредственно с ОС, а объект Thread не поддерживает поле, хранящее приоритет потока. Другой пример свойств, не имеющих резервных полей, — это неизменяемые свойства, вычисляемые при выполнении: длина массива, заканчивающегося нулем, или область прямоугольника, заданного шириной и высотой и т. д.
При обработке компилятором кода, написанного выше, он определит, что есть свойство. Далее представит его в виде двух методов get_MethodName и set__MethodName.