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

    На этом шаге мы рассмотрим оформление свойства, как статического.

    Свойство может быть статическим. С технической точки зрения особенность такого свойства в том, что оно описывается с ключевым словом static. Но поскольку свойство не связано с областью памяти, то наличие в классе статического свойства обычно подразумевает, что для реализации этого свойства используются статические поля. Неболыной пример, показывающий, как может быть описано статическое свойство, представлен в примере ниже.

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

namespace pr126_1
{
    // Класс со статическим свойством: 
    class Fibs
    {
        // Закрытые целочисленные статические поля: 
        private static int last = 1;
        private static int prev = 1;
        // Статическое целочисленное свойство: 
        public static int number
        {
            // Метод вызывается при считывании значения свойства: 
            get
            {
                // Локальная переменная: 
                int res = prev;
                // Изменение значения статических полей:
                last = last + prev;
                prev = last - prev;
                // Значение свойства: 
                return res;
            }
            // Метод вызывается при присваивании
            // значения свойству:
            set
            {
                // Начальное значение статических полей:
                prev = 1;
                last = 1;
                // Изменение значения статических полей: 
                for (int k = 2; k <= value; k++)
                {
                    last = last + prev;
                    prev = last - prev;
                }
            }
        }
    }

    // Класс с главным методом: 
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Отображение значения статического свойства: 
            for(int k = 1; k <= 10; k++){
                Console.Write("{0,4}", Fibs.number);
            }
            Console.WriteLine();
            // Присваивание значения статическому свойству: 
            Fibs.number = 6;
            // Отображение значения статического свойства: 
            for(int k = 1; k <= 10; k++){
                Console.Write("{0,4}", Fibs.number);
            }
            Console.WriteLine();
            // Присваивание значения статическому свойству: 
            Fibs.number = 1;
            // Отображение значения статического свойства: 
            for(int k = 1; k <= 10; k++){
                Console.Write("{0,4}", Fibs.number);
            }
            Console.WriteLine();
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

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


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

    Мы описали класс Fibs со статическим свойством number. При проверке значения свойства результатом оно возвращает число из последовательности Фибоначчи. Причем каждый раз это число новое.


В последовательности Фибоначчи два первых числа равны 1, а каждое следующее число - это сумма двух предыдущих чисел. Получается последовательность чисел 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 и так далее.

    При присваивании значения свойству number число, которое присваивается свойству, определяет порядковый номер числа из последовательности Фибоначчи, которое будет возвращаться в качестве значения свойства. Например, если мы присваиваем свойству number значение 6, то это означает, что при считывании значения свойства мы получим значение 8, поскольку именно число 8 является шестым по счету в последовательности Фибоначчи. Если далее мы еще раз прочитаем значение свойства number, то получим значение 13, а затем при считывании значения свойства получим значение 21 и гак далее.

    Для реализации такого подхода мы описываем два закрытых целочисленных статических поля last и prev с начальными единичными значениями. Эти поля нам нужны для того, чтобы записать в них значения двух последних чисел из последовательности Фибоначчи. Нам нужно именно два числа, поскольку следующее число в последовательности вычисляется как сумма двух предыдущих. Начальные значения полей объясняются тем, что первые два числа в последовательности - это 1 и 1.

    Свойство number описано с ключевым словом static. В get-аксессоре свойства объявляется локальная переменная res, в которую записывается значение поля prev. Затем выполняются две команды

  last = last + prev;
и
  prev = last - prev;                , 
которыми полю last значением присваивается новое число Фибоначчи, а полю prev значением присваивается то число, которое раньше было записано в поле last. После этого значение переменной res (то значение, которое в самом начале было записано в поле prev) возвращается как значение свойства. Таким образом, получается, что при считывании значения свойства number результатом возвращается значение поля prev, а затем вычисляется новое число Фибоначчи и обновляются значения полей last и prev гак, что поле last содержит значение нового вычисленного числа, а в поле prev записывается значение предыдущего числа.


Допустим, поля prev и last содержат два числа из последовательности Фибоначчи. Наша задача - сделать "шаг вперед": вычислить новое число Фибоначчи и записать в поля новую пару чисел. Чтобы понять алгоритм вычислений, обозначим исходное значение поля prev как Δ, а исходное значение поля last обозначим как . Необходимо сделать так, чтобы в поле last было записано значение Δ + ◊, а в поле prev должно быть записано значение . После выполнения команды last=last+prev в поле last записывается значение Δ + ◊. Поле prev остается со значением Δ. После выполнения команды prev=last-prev поле prev получает значение , что нам и нужно.

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

 prev = l ;
и
  last = l; 
полям prev и last присваиваются единичные значения. После этого запускается цикл, в котором индексная переменная к принимает значения от 2 до присваиваемого свойству значения value. За одну итерацию цикла выполняются команды
  last = last + prev; 
и
  prev = last - prev;    . 
Каждый раз, когда выполняются эти команды (мы их анализировали выше), вычисляется новое число Фибоначчи. С учетом того, что начальные единичные значения полей prev и last соответствуют первой паре чисел в последовательности, а первое значение индексной переменной k в конструкции цикла равно 2, то после выполнения конструкции цикла в поле prev будет записано число из последовательности Фибоначчи, порядковый номер которого определяется значением value, присваиваемым свойству. В поле last будет записано следующее число в последовательности.

    В главном методе программы запускается конструкция цикла, в которой выполняется 10 итераций. За каждую итерацию в консольном окне отображается значение, возвращаемое инструкцией Fibs.number.


В теле цикла выполняется команда
  Console.Write("{0,4}", Fibs.number);    . 
Инструкция {0,4} означает, что отображается значение выражения Fibs.number и под это значение (число) отводится 4 позиции.

    В результате в консольном окне отображаются первые 10 чисел из последовательности Фибоначчи. Затем командой

  Fibs.number = 6;
присваивается значение свойству number. Затем снова выполняется цикл и 10 раз подряд отображается значение статического свойства number. В итоге получаем еще одну строку из 10 чисел Фибоначчи, но на этот раз числа отображаются, начиная с шестого числа. Наконец, после выполнения команды
  Fibs.number = 1;
и выполнения цикла получаем строку из 10 чисел Фибоначчи, начиная с первого числа в последовательности.

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




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