Шаг 121.
Язык программирования C#. Начала
Свойства и индексаторы. Знакомство со свойствами (окончание)

    На этом шаге мы рассмотрим пример создания и использования свойств.

    В примере ниже представлена программа, в которой есть класс, а в этом классе есть свойство.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr121_1
{
    // Класс со свойством: 
    class MyClass {
        // Закрытые целочисленные поля: 
        private int num; 
        private int min; 
        private int max;
        // Конструктор с двумя аргументами: 
        public MyClass(int a, int b) {
            // Присваивание значения полям:
            min = a;
            max = b;
            // Присваивание значения свойству: 
            code = (max + min) / 2;
        }
        // Описание целочисленного свойства: 
        public int code{
            // Метод вызывается при считывании значения свойства: 
            get{
                // Значение свойства: 
                return num;
            }
            // Метод вызывается при присваивании
            // значения свойству:
            set{
                // Если присваиваемое значение меньше минимально 
                // допустимого: 
                if ( value < min ) num = min;
                // Если присваиваемое значение больше максимально
                // допустимого:
                else 
                    if ( value > max) num = max;
                    // Если присваиваемое значение попадает в 
                    // допустимый диапазон: 
                    else num = value;
            }
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Создание объекта:
            MyClass obj = new MyClass(1, 9);
            // Проверка значения свойства:
            Console.WriteLine("Свойство code: " + obj.code);
            // Присваивание значения свойству: 
            obj.code = 7;
            // Проверка значения свойства:
            Console.WriteLine("Свойство code: " + obj.code);
            // Присваивание значения свойству: 
            obj.code = 20;
            // Проверка значения свойства:
            Console.WriteLine("Свойство code: " + obj.code);
            // Присваивание значения свойству: 
            obj.code = -10;
            // Проверка значения свойства:
            Console.WriteLine("Свойство code: " + obj.code);
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы такой, как показано ниже.


Рис.1. Результат выполнения программы

    В программе мы описываем класс с названием MyClass. В классе описаны три целочисленных закрытых поля num, min и max. В классе есть конструктор с двумя аргументами (код конструктора мы осудим позже). Но наиболее интересное для нас место в классе - описание свойства с названием code. Свойство описано с идентификаторами public и int, что означает, что свойство открытое и целочисленное. Свойство описано с двумя методами-аксессорами. В теле get-акссссора всего одна команда return num, которой значением свойства возвращается значение поля num.


Поскольку свойство code описано как такое, что относится к типу int, то get-аксессор, описанный для этого свойства, должен возвращать значение типа int.

    При присваивании значения свойству code будет вызываться set-аксессор, описанный для свойства. В соответствии с кодом этого аксессора выполняются вложенные условные операторы. В этих условных операторах проверяется присваиваемое свойству значение (это значение отождествляется с ключевым словом value). Если это значение меньше значения поля min (условие value < min истинно), то поле num получает значение min при выполнении команды

  num = min;    . 

    Если присваиваемое свойству значение больше значения ноля max (условие value > max истинно), то полю num присваивается значение max, команда

  num = max;    . 

    Иначе (если присваиваемое свойству значение попадает в диапазон значений от min до max) полю num присваивается то значение, которое собственно указано справа от оператора присваивания: команда

  num = value;   . 

    Мы не объявляли переменную с названием value. Это ключевое слово, обозначающее присваиваемое свойству значение. Вполне разумно отождествлять идентификатор value с некоторой переменной. Причем у переменной есть тип - это тип свойства, которому присваивается значение. В нашем примере value отождествляется с целочисленным значением (тип int).

    Что в итоге получается? Получается, что при запросе значения свойства code в действительности возвращается значение поля num. Само поле num закрытое, поэтому вне кода класса значение этому полю напрямую присвоить не удастся. Значение ноля num изменяется при присваивании значения свойству code. Алгоритм присваивания не сводится к копированию присваиваемого значения в поле num. Мы хотим, чтобы значение поля num не могло быть меньше значения поля min, а также чтобы оно не могло быть больше значения поля max. Поэтому если присваиваемое свойству code значение попадает в диапазон значений от min до max, то поле num получает то значение, которое реально присваивается. Если же присваиваемое значение выходит за пределы допустимого диапазона значений, то поле num получает минимально/максимально возможное значение (в зависимости от того, за какую границу "выскакивает" присваиваемое значение).

    Что касается конструктора класса MyClass, то два его аргумента определяют минимальное и максимальное значение для свойства code (значения полей min и max), а командой

  code = (max + min) / 2; 
свойству code (а значит, и полю num) присваивается начальное значение.


После создания объекта класса MyClass значения полей min и mах этого объекта уже изменить нельзя. Значение поля num изменяется при присваивании значения свойству code объекта.

    В главном методе программы командой

  MyClass obj = new MyClass(1, 9);
создается объект obj класса MyClass. Таким образом, значение свойства code объекта obj не может выходить за пределы значений от 1 до 9 включительно. Начальное значение свойства code равно 5 (поскольку (1+9)/2=5). При выполнении команды
  obj.code = 7; 
свойство code (поле num) получит значение 7. Выполнение команды
  obj.code = 20; 
приводит к тому, что свойство code (поле num) получит значение 9. Наконец, выполнение команды
  obj.code = -10; 
приведет к тому, что свойство code (поле num) получит значение 1.


Подумайте, что произойдет, если при создании объекта класса MyClass значение первого аргумента конструктора будет больше значения второго аргумента конструктора. Предложите способ реорганизации программного кода конструктора, чтобы при создании объекта класса MyClass значение поля mах не могло быть меньше значения поля min.

    На следующем шаге мы более детально остановимся на использовании свойств.




Предыдущий шаг Содержание Следующий шаг