Урок 4. Конструкторы и финализаторы C#


На четвёртом уроке учебника по объектно-ориентированному программированию на языке C# рассматриваются конструкторы и финализаторы. Эти специальные методы позволяют инициализировать объект при создании экземпляра и выполнять действия перед его удалением из памяти.

Конструкторы

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

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

В этой статье мы создадим новый класс для представления треугольной формы. Данный класс определяет три свойства: высоту треугольника, длину основания и площадь. Для начала создайте новое консольное приложение и добавьте класс с именем "Triangle". Скопируйте и вставьте следующий код в класс, чтобы создать три обязательных свойства.

public class Triangle
{
    private int _height;
    private int _baseLength;
 
    public int Height
    {
        get
        {
            return _height;
        }
        set
        {
            if (value < 1 || value > 100)
            {
                throw new OverflowException();
            }
 
            _height = value;
        }
    }
 
    public int BaseLength
    {
        get
        {
            return _baseLength;
        }
        set
        {
            if (value < 1 || value > 100)
            {
                throw new OverflowException();
            }
 
            _baseLength = value;
        }
    }
 
    public double Area
    {
        get
        {
            return _height * _baseLength * 0.5;
        }
    }
}
Конструктор по умолчанию

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

Замена конструктора по умолчанию

Синтаксис добавления нового конструктора в класс аналогичен синтаксису добавления метода. Однако конструктор имеет то же имя, что и класс, и не содержит возвращаемого типа. Поэтому объявление нового конструктора Triangle является простым:

public Triangle()
Чтобы гарантировать, что все треугольники будут иметь высоту и базовую длину в допустимом диапазоне, мы заставим конструктор класса установить оба этих свойства в единицу для всех новых объектов треугольника. Это достигается простым заданием базовых частных переменных в блоке кода конструктора. Добавьте следующий код в блок кода класса, чтобы добавить конструктор.

public Triangle()
{
    Console.WriteLine("Triangle constructor executed");
 
    _height = _baseLength = 1;
}
Выполнение конструктора

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

static void Main(string[] args)
{
    Triangle triangle = new Triangle();
 
    Console.WriteLine("Height:\t{0}", triangle.Height);
    Console.WriteLine("Base:\t{0}", triangle.BaseLength);
    Console.WriteLine("Area:\t{0}", triangle.Area);
}
 
/* OUTPUT
 
Triangle constructor executed
Height: 1
Base:   1
Area:   0.5
 
*/
Параметризованные конструкторы

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

public Triangle(int height, int baseLength)
{
    Console.WriteLine("Triangle constructor executed");
 
    this.Height = height;
    this.BaseLength = baseLength;
}
Если вы попытаетесь скомпилировать или выполнить консольное приложение, то получите сообщение об ошибке компилятора, указывающее, что нет конструктора, который принимает нулевые аргументы. Это связано с тем, что основной метод все еще пытается использовать конструктор по умолчанию. Поскольку он был заменен, основной метод должен быть скорректирован для использования новой, параметризованной версии следующим образом:

static void Main(string[] args)
{
    Triangle triangle = new Triangle(5,8);
 
    Console.WriteLine("Height:\t{0}", triangle.Height);
    Console.WriteLine("Base:\t{0}", triangle.BaseLength);
    Console.WriteLine("Area:\t{0}", triangle.Area);
}
 
/* OUTPUT
 
Triangle constructor executed
Height: 5
Base:   8
Area:   20
 
*/
Финализатор

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

В других языках .NET метод Finalize класса объекта может быть переопределен для предоставления кода очистки. В C# это не разрешено, и используется специальный синтаксис финализатора. Это также приводит к вызову метода завершения базового класса объекта, неявно Преобразуя операторы метода завершения в приведенный ниже код Finalize:

protected override void Finalize()
{
    try
    {
        // Finalizer code
    }
    finally
    {
        base.Finalize();
    }
}
Создание финализатора

Синтаксис для создания финализатора очень прост. Имя класса предваряется символом Тильды (~). Никакие параметры не разрешены, так как финализатор не может быть вызван вручную. Чтобы добавить финализатор в класс Triangle, добавьте следующий код:

~Triangle()
{
    Console.WriteLine("Triangle finalizer executed");
}
Примечание: финализатор выводит сообщение только в том случае, если очистка объектов треугольника не требуется.

Выполнение финализатора

Финализатор выполняется автоматически при удалении объекта из памяти. Это можно продемонстрировать, запустив консольное приложение. Результат должен быть следующим:

Triangle constructor executed
Height: 5
Base:   8
Area:   20
Triangle finalizer executed
Примечание: классы, требующие финализаторов, также должны реализовывать интерфейс IDisposable.

Сборка мусора

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

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

Сбора мусора и финализация

Система сбора мусора полностью автоматизирована и не требует особого внимания со стороны разработчика C#. Однако важно понимать, что финализатор объекта не вызывается сразу, что он выпадает из области видимости. Может быть задержка, пока сборщик мусора не решит восстановить память объекта, и только в этот момент вызывается финализатор.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, си шарп, ООП




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Демонстрация Q-learning в программе на Java
Начало работы с PhantomJS
Урок 1. HelloWorld