Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1447 / 157 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 7:

Основы языка C#. Часть 1

< Лекция 6 || Лекция 7: 12345 || Лекция 8 >

Константные поля класса

Для создания более надежного кода часть работы программист перекладывает на компилятор, заставляя последний отслеживать действия программиста. Именно для этого существуют константы как особый тип переменных, значения которых изменять не предполагается. Объявление константной переменной выполняется с помощью ключевого слова const, при этом переменная должна быть инициализирована значением сразу при ее объявлении. В дальнейшем любая попытка изменить значение константной переменной приведет к ошибке компиляции.

Константы можно объявлять на уровне полей или локальных переменных. Константы нельзя инициализировать ссылкой, значение которой вычисляется во время выполнения программы, но можно инициализировать выражением, значение которого вычисляется во время компиляции. При этом значения константных полей или переменных сразу вычисляются компилятором и подставляются вместо идентификаторов констант.

В приведенном примере тип класса содержит константные поля, которые инициализируются во время компиляции

using System;
    
class MyClass
{
    public const string MESSAGE = "Привет!";
    public const double PI = 3.14;
    public const bool TRUE = true;
    public const bool FALSE = !TRUE;
    
    public MyClass()
    {
        Console.WriteLine("{0} {1} {2} {3}",
            MESSAGE, PI, TRUE, FALSE);
    }
}
    
class Start
{
    static void Main()
    {
        MyClass myClass = new MyClass();
        Console.ReadLine();
    }
}
Листинг 7.5 . Использование константных полей внутри класса

Для отличия констант от переменных их имена принято обозначать в верхнем регистре. Поскольку во всех экземплярах класса значение константных полей класса будет одно и то же, то эти поля-константы считаются неявно статическими и в вызывающем коде к ним нужно адресоваться по имени класса, а не по имени объекта. Если константное поле или переменная определены в области видимости блока кода, то к ним можно адресоваться напрямую.

using System;
    
class MyClass
{
    // Объявление константных полей
    public const string MESSAGE = "Привет!";
    public const double PI = 3.14;
    public const bool TRUE = true;
    public const bool FALSE = !TRUE;
}
    
class Start
{
    static void Main()
    {
        // Вызов полей из вне по имени класса
        Console.WriteLine("{0} {1} {2} {3}",
            MyClass.MESSAGE, MyClass.PI, MyClass.TRUE, MyClass.FALSE);
    
        // Локальная константа вызывается напрямую
        const int LOCAL_VARIABLE = 123;
        Console.WriteLine(LOCAL_VARIABLE);
    
        Console.ReadLine();
    }
}
Листинг 7.6. Использование константных полей вне класса

Обратите внимание, что в приведенных кодах нет объявления пространства имен, тогда по умолчанию код размещается в глобальном пространстве имен. Для простых примеров это не опасно, но в больших проектах есть угроза дублирования имен типов.

Поля класса "только для чтения"

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

using System;
    
class Circle
{
    // Объявление константного поля с отложенной инициализацией
    public readonly int radius;
    
    public Circle(int radius)
    {
        this.radius = radius;// Две разных переменных!!!
    }
}
    
class Start
{
    static void Main()
    {
        // Инициализация константного поля при создании экземпляров
        Circle circle1 = new Circle(5);
        Circle circle2 = new Circle(10);
        Console.WriteLine("r1={0}; r2={1}",
            circle1.radius, circle2.radius);
    
        // Попытка переприсваивания значения приведет к ошибке компиляции
        // circle1.radius = 20;
        // circle2.radius = 30;
     
        Console.ReadLine();
    }
}
Листинг 7.7. Использование полей "только для чтения"

Если убрать модификатор readonly в объявлении переменной radius, то никакой ошибки компиляции не будет. Это значит, что хоть программист и полагает, что после создания объекта значение поля меняться не будет, но нет гарантии, что внутри класса или вне его не произойдет случайного переприсваивания - компилятор на это место уже не укажет. Ключевое слово this отличает переменную-поле класса от параметра конструктора.

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

Пусть у нас есть два заветных круга (семейный и друзей!), радиус которых никогда не должен меняться. Упакуем их в тот же класс и определим объекты доступными на уровне класса. Для этого их нужно сделать статическими. Вот этот код

using System;
    
class Circle
{
    // Объявление неизменяемого поля с отложенной инициализацией
    public readonly int radius;
    
    // Динамически создаем объект уровня класса 
    // и адресуем его неизменяемым полем-ссылкой
    public static readonly Circle circle1 = new Circle(5);
    public static readonly Circle circle2 = new Circle(10);
    
    public Circle(int radius)
    {
        this.radius = radius;
    }
}
    
class Start
{
    static void Main()
    {
        // Объекты создавать не нужно, они уже существуют в классе
        // Просто выводим значения готовых объектов из класса
        Console.WriteLine("r1={0}; r2={1}",
            Circle.circle1.radius, Circle.circle2.radius);
     
        Console.ReadLine();
    }
}
Листинг 7.8. Применение неизменяемых полей-ссылок уровня класса

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

< Лекция 6 || Лекция 7: 12345 || Лекция 8 >
Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.

 

Как активировать код?