private int empAge;
public Employee(string fullName, int age,int empID, float currPay) {
…
this.empAge= age;
}
public int Age {
get { return empAge; }
set { empAge = value; }
}
public void DisplayStats() {
…
Console.WriteLine("Возраст: {0}", empAge);
}
}
Теперь предположим, что вы создали объект Employee с именем joe. Вы хотите, чтобы в день рождения работника значение переменной возраста увеличивалось на единицу. Используя традиционные методы чтения и модификации, вы должны применить, например, следующий программный код.
Employee joe = new Employee();
joe. SetAge(joe. GetAge() + 1);
Но если инкапсулировать empAge, используя "правильный" синтаксис, вы сможете просто написать:
Employee joe = new Employee();
joe. Age++;
Внутреннее представление свойств в C#
Многие программисты (особенно те, которые привыкли использовать C++) стремятся использовать традиционные префиксы get_ и set_ для методов чтения и модификации (например, get_FullName() и set_FullName()). Против самого соглашения возражений нет. Однако следует знать, что "за кадром" свойства в C# представляются программным кодом CIL, использующим такие же префиксы. Например, если открыть компоновочный блок Employees.exe с помощью ildasm.exe, вы увидите, что каждое свойство XXX на самом деле сводится к скрытым методам get_XXX()/set_XXX() (рис. 4.6).
Рис. 4.6. Отображение свойств XXX в скрытые методы get_XXX() и set_XXX()
Предположим теперь, что тип Employee имеет частный член-переменную с именем empSSN для представления номера социальной страховки работника. Эта переменная устанавливается через параметр конструктора, а для управления этой переменной используется свойство SocialSecurityNumber.
// Добавление поддержки нового поля, представляющего SSN-код.
public class Employee {
…
// Номер социальной страховки (SSN).
private string empSSN;
public Employes (string fullName, int age, int empID, float currPay, string ssn){
…
this. empSSN= ssn;
}
public string SocialSecurityNumber {
get { return empSSN; }
set { empSSN = value; }
}
public void DisplayStats() {
…
Console.WriteLine("SSN: {0} ", empSSN);
}
}
Если бы вы также определили два метода get_SocialSecurityNumber() и set_SocialSecurityNumber(), то получили бы ошибки компиляции.
// Свойство в C# отображается в пару методов get_/set_.
public class Employee {
// ОШИБКА! Уже определены самим свойством!
public string get_SocialSecurityNumber() { return empSSN; }
public void set_SocialSecurityNumber(string val) { empSSN = val; }
}
Замечание.В библиотеках базовых классов .NET всегда отдается предпочтение свойствам типа (в сравнении с традиционными методами чтения и модификации). Поэтому, чтобы строить пользовательские типы, которые хорошо интегрируются с платформой .NET, следует избегать использования традиционных методов get и set.
Контекст операторов get и set для свойств
До появления C# 2005 область видимости get и set задавалась исключительно модификаторами доступа в определении свойства.
// Логика get и set здесь открыта,
// в соответствии с определением свойства.
public string SocialSecurityNumber {
get {return empSSN;}
set {empSSN = value;}
}
В некоторых случаях бывает нужно указать свои области видимости для методов get и set. Чтобы сделать это, просто добавьте префикс доступности (в виде соответствующего ключевого слова) к ключевому слову get или set (при этом область видимости без уточнения будет соответствовать области видимости из определения свойства).
// Пользователи объекта могут только получить значение,
// но производные типы могут также установить значение.
public string SocialSecurityNumber {
get { return empSSN;}
protectedset {empSSN = value;}
}
В данном случае логика set для SocialSecurityNumber может вызываться только данным классом и производными классами, а поэтому не может быть доступна на уровне экземпляра объекта.
Свойства, доступные только для чтения, и свойства, доступные только для записи
При создании типов класса можно создавать свойства, доступные только для чтения. Для этого просто создайте свойство без соответствующего блока set. Точно так же, если вы хотите иметь свойство, допускающее только запись, опустите блок get. Для нашего примера в этом нет необходимости, но вот как можно изменить свойство SocialSecurityNumber, чтобы оно было доступно только для чтения.
Читать дальше