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

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

    Еще одна программа, иллюстрирующая использование сразу нескольких свойств в одном классе, представлена в листинге 9.5.

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

namespace pr125_1
{
    // Класс со свойствами: 
    class MyClass {
        // Закрытое поле-массив: 
        private int[] nums;
        // Текстовое свойство без set-аксессора: 
        public string content {
            // Метод вызывается при считывании значения свойства: 
            get {
                // Если ссыпка на массив пустая: 
                if( nums == null ) return "{}";
                // Формирование текстовой строки: 
                string txt = "{" + nums[0]; 
                for(int k = 1; k < nums.Length; k++) {
                    txt += "," + nums[k];
                }
                txt += "}";
                // Значение свойства: 
                return txt;
            }
        }
        // Целочисленное свойство без get-аксессора: 
        public int element {
            // Метод вызывается при присваивании
            // значения свойству:
            set {
                // Если ссылка на массив пустая: 
                if( nums == null ) {
                    // Создание массива из одного элемента: 
                    nums = new int[1];
                    // Значение единственного элемента массива: 
                    nums[0] = value;
                }
                else {
                    // Если ссылка не пустая 
                    // Создание массива: 
                    int[] n = new int[nums.Length + 1];
                    // Заполнение массива: 
                    for(int k = 0; k < nums.Length; k++){ 
                       n[k] = nums[k];
                    }
                    // Значение последнего элемента в массиве: 
                    n[nums.Length] = value;
                    // Ссылка на созданный массив записывается в
                    // поле объекта:
                    nums = n;
                }
            }
        }
        // Свойство является ссылкой на массив: 
        public int[] data {
            // Метод вызывается при считывании значения свойства: 
            get {
                // Создание массива:
                int[] res = new int[nums.Length];
                // Заполнение массива: 
                for(int k = 0; k < nums.Length; k++) {
                    res[k] = nums[k];
                }
                // Значение свойства: 
                return res;
            }
            // Метод вызывается при присваивании
            // значения свойству:
            set {
                // Создание массива: 
                nums = new int[value.Length];
                // Заполнение массива: 
                for (int k = 0; k < value.Length; k++){ 
                    nums[k] = value[k];
                }
            }
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Создание объекта:
            MyClass obj = new MyClass();
            // Проверка содержимого массива из объекта: 
            Console.WriteLine(obj.content);
            // Присваивание значения свойству element: 
            obj.element = 10;
            // Проверка содержимого массива из объекта: 
            Console.WriteLine(obj.content);
            // Присваивание значения свойству element: 
            obj.element = 5; 
            obj.element = 7;
            // Проверка содержимого массива из объекта: 
            Console.WriteLine(obj.content);
            // Считывание значения свойства data: 
            int[] A = obj.data;
            // Присваивание значения свойству element:
            obj.element = 12;
            // Отображение содержимого массива А: 
            for(int k = 0; k < A.Length; k++) {
                Console.Write(A[k] + " ");
            }
            Console.WriteLine();
            // Проверка содержимого массива из объекта:
            Console.WriteLine(obj.content);
            // Создание массива: 
            int[] B = {11, 3, 6};
            // Присваивание значения свойству data: 
            obj.data = B;
            // Изменение значения элемента массива В:
            B[0] = 0;
            // Отображение содержимого массива В: 
            for(int k = 0; k < B.Length; k++){
                Console.Write(B[k] + " ");
            }
            Console.WriteLine();
            // Проверка содержимого массива из объекта:
            Console.WriteLine(obj.content);
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    В результате выполнения программы получаем следующее.


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

    Класс MyClass имеет закрытое поле nums, представляющее собой ссылку на целочисленный массив. Этот массив используется при описании свойств content, element и data. Свойство content текстовое, и у этого свойства есть только get-аксессор (свойство можно прочитать, но нельзя присвоить). Свойство возвращает текстовую строку со значениями элементов массива. При вызове get-аксессора для этого свойства в условной конструкции проверяется условие nums==null, истинное, если поле nums не ссылается на массив. Если так, то значением свойства возвращается строка "{}".


Ключевое слово null означает пустую ссылку. Если переменной ссылочного типа (переменной массива или объектной переменной) не присвоено значение, то значение такой переменной - пустая ссылка (то есть равно null).

    Если же поле nums ссылается на массив, то формируется текстовая прока, содержащая значения элементов массива, и эта строка возвращается как значение свойства content.

    Целочисленное свойство element не имеет get-аксессора, поэтому свойству можно присвоить значение, но нельзя узнать значение свойства. При присваивании значения свойству в массив nums добавляется новый элемент с присваиваемым значением. Для этого в теле set-аксессора в условной конструкции проверяется условие nums==null. Истинность условия означает, что поле nums на массив не ссылается. В таком случае командой

  nums = new int[1];
создается массив из одного элемента, и значение этого элемента есть присваиваемое свойству значение:
  nums[0] = value;          .

    Если условие nums==null в условной конструкции ложно, то командой

  int[] n = new int[nums.Length + 1];
создается новый массив, размер которого на единицу больше размера массива, на который ссылается поле nums. Сначала выполняется поэлементное копирование значений из массива nums во вновь созданный массив. Остается незаполненным один последний элемент. Командой
  n[nums.Length] = value;
этому элементу присваивается значение, которое по факту присваивается свойству element. Наконец, командой
  nums = n;
в поле nums записывается ссылка на новый массив. Общий эффект получается такой, что в массиве, на который ссылается поле nums, появился дополнительный последний элемент.

    Свойство data является ссылкой на целочисленный массив. Для свойства описаны два аксессора. Это означает, что свойству значением можно присвоить ссылку на массив и результатом свойства является также ссылка на массив.

    В get-аксессоре для этого свойства командой

  int[] res = new int[nums.Length];
создается массив такого же размера, что и массив, на который ссылается поле nums. Затем выполняется копирование массивов. Значением свойства является ссылка на новый созданный массив, являющийся копией массива, на который ссылается поле nums.


Свойство data значением возвращает ссылку на массив, который является копией массива, на который ссылается поле nums объекта.

    В set-аксессоре для свойства data командой

  nums = new int[value.Length];
создается новый массив, и ссылка на него записывается в поле nums. Здесь следует учесть, что ключевое слово value, обозначающее присваиваемое свойству значение, относится к типу int[] (тип свойства data) - то есть является ссылкой на целочисленный массив и обрабатывается как массив. Размер такого массива вычисляется выражением value.Length. С помощью циклической конструкции выполняется копирование значений элементов из присваиваемого массива value в созданный массив nums.

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

  MyClass obj = new MyClass();
создается объект obj класса MyClass. Его поле nums на массив не ссылается, в чем легко убедиться с помощью команды
  Console.WriteLine(obj.content);
Присваивание значения свойству element командой
  obj.element = 10;
приводит к тому, что в массиве nums появляется один элемент. После выполнения команд
  obj.element = 5;
и
  obj.element = 7;
там появляется еще два элемента.

    На следующем этапе командой

  int[] A = obj.data;
объявляется переменная массива А и в нее записывается ссылка на копию массива, на который ссылается поле nums объекта obj. Чтобы проверить, что это именно копия, а не сам массив nums, командой
  obj.element = 12;
в массив nums объекта obj добавляется еще один элемент. При этом массив А остается неизменным, в чем легко убедиться, сравнив результат отображения содержимого массива А и массива nums из объекта obj.

    Далее командой

  int[] B = {11, 3, 6};
создается целочисленный массив В, и командой
  obj.data = B;
ссылка на массив присваивается значением свойству data объекта obj. В результате поле nums объекта получает значением ссылку на копию массива B. Действительно, проверка показывает, что после выполнения команды
  B[0] = 0;
массив B меняется, а массив, на который ссылается поле nums объекта obj, остается таким, как до выполнения команды
  B[0] = 0;        .

    На следующем шаге мы рассмотрим закончим изучение этого вопроса.




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