На этом шаге мы рассмотрим назначение и общую схему использования свойств.
Мы начинаем знакомство со свойствами. Свойство - это член класса, как поле или метод. Но это и не поле, и не метод. Свойство в языке C# - это нечто среднее между полем и методом. Если исходить из того, как свойство используется, то оно, конечно, очень напоминает поле. Но принципы реализации свойства больше напоминают описание методов. Чтобы было легче понять, как свойство описывается в классе, начнем с того, как оно используется.
Используется свойство, как отмечалось выше, практически так же, как поле. Для большей конкретики представим, что существует некий объект и у этого объекта есть поле (например, числовое). Что мы можем делать с этим полем? В принципе, есть две базовые операции:
При описании свойства определяются два специальных метода, которые непосредственно связаны со свойством. Эти методы называются аксессорами. Один метод (называется get-аксессором) вызывается при считывании значения свойства. Другой метод (называется set-аксессором) вызывается при присваивании значения свойству. Проще говоря, при считывании значения свойства и при присваивании значения свойству вызываются специальные методы (в отличие от случая с полем, когда обращение к полю означает обращение к области памяти, в которой хранится значение поля). Что будет происходить при вызове методов-аксессоров, определяем мы, когда описываем свойство в классе. Это может быть банальное считывание/присваивание значения некоторому полю, определенный вычислительный процесс, обращение к массиву или другому объекту - все зависит от нашей фантазии и той задачи, которая решается. В этом смысле свойство близко к методу, причем не одному методу, а сразу двум методам. Считывание значения свойства означает вызов метода, возвращающего значение (значение свойства). Присваивание значения свойству подразумевает вызов другого метода, который может присваивать значения полям или выполнять иные полезные действия.
Описывается свойство немного сложнее, чем поле (оно и понятно - в общем случае со свойством связано два метода-аксессора, которые также нужно описать при описании свойства). Вначале указывается тип и название свойства (как и при описании поля), затем в блоке в фигурных скобках описываются методы-аксессоры. Эти методы (их обычно два) описываются специальным образом.
Метод, вызываемый при считывании значения свойства (get-аксессор), описывается следующим образом: указывается ключевое слово get, после которого в фигурных скобках описываются команды, выполняемые при считывании значения свойства. То есть никаких формальных атрибутов метода (тип результата, название, список аргументов) здесь нет. Объяснение простое. Уникальное название методу не нужно, поскольку метод "самостоятельной ценности" не имеет и вызывается при обращении к свойству (то есть имя свойства "замещает" имя метода). Аргументы методу не нужны по определению, поскольку при считывании значения свойства никакие дополнительные значения или атрибуты не используются. А вот результат метод возвращает (хотя идентификатор типа результата явно никак не обозначен). Возвращаемый get-аксессором результат - это значение свойства. Поэтому тип результата get-акссссора совпадает с типом свойства.
Метод, который вызывается при присваивании значения свойству (set-аксессор), описывается таким образом: указывается ключевое слово set, а в фигурных скобках описываются команды, выполняемые при присваивании значения свойству. Данный метод-аксессор не возвращает результат, и у него нет аргументов. Но один параметр методу все же нужен: это значение, которое присваивается свойству. Поскольку аргумента у метода нет, то аргументом данное значение в метод передать нельзя. Поэтому присваиваемое свойству значение в set-аксессор передается с помощью ключевого слова value. Это ключевое слово, которое в блоке описания set-аксессора отождествляется со значением, присваиваемым свойству.
Ниже представлен шаблон, в соответствии с которым описывается свойство:
тип имя { get { // Код get-аксессора } set { // Код set-аксессора } }
При описании свойства можно определить не два, а только один аксессор: или get-аксессор, или set-аксессор. Если для свойства определен только get-аксессор, то значение такого свойства можно прочитать, но такому свойству нельзя присвоить значение. Если для свойства определен только set-аксессор, то значение свойству можно присвоить, но нельзя его прочитать.
Еще одна важная особенность свойства состоит в том, что под свойство место в памяти не выделяется. То есть из того факта, что мы описали свойство, не следует, что при создании объекта под это свойство выделяется память. В этом смысле свойство принципиально отличается от поля. Поэтому если мы собираемся при работе со свойством запоминать и использовать некоторое значение, то нам придется для этого специально описать поле (обычно закрытое). Фактически свойство - это некая "ширма", за которой может "скрываться" все, что угодно.
На следующем шаге мы закончим изучение этого вопроса.