Шаг 85.
Язык программирования C#. Начала
Знакомство с классами и объектами. Деструктор

    На этом шаге мы рассмотрим назначение, синтаксис и особенности использования деструктора.

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

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


Как отмечалось выше, деструктор автоматически вызывается при удалении объекта из памяти. Но проблема в том, что выход объекта из области видимости (потеря ссылки на объект) не означает, что объект будет сразу же удален. Он будет удален, но это может произойти через некоторое время. За удаление "ненужных" объектов отвечает система "сборки мусора". Она работает автономно и удаляет те объекты, на которые в программе нет ссылок. Поэтому, если на объект теряется последняя ссылка, он автоматически становится кандидатом на удаление. Когда именно он будет удален, "решает" "сборщик мусора", а не программа. Деструктор вызывается при удалении объекта. Получается, что точное время вызова деструктора неизвестно. Мы лишь знаем, что он будет вызван. Эту особенность нужно учитывать при использовании деструкторов в классах.

    Иллюстрация к использованию деструктора в программе представлена в примере ниже.

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

namespace pr85_1
{
    // Класс с конструктором и деструктором: 
    class MyClass
    {
        // Закрытое текстовое поле: 
        private string name;

        // Конструктор:
        public MyClass(string txt)
        {
            // Присваивание значения полю: 
            name = txt;
            // Отображение сообщения:
            Console.WriteLine("Создан объект \"{0}\"", name);
        }

        // Деструктор:
        ~MyClass()
        {
            // Отображение сообщения:
            Console.WriteLine("Удален объект \"{0}\"", name);
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Статический метод: 
        static void maker(string txt)
        {
            // Создание анонимного объекта: 
            new MyClass(txt);
        }

        // Главный метод:
        static void Main()
        {
            // Создание объекта:
            MyClass A = new MyClass("Первый"); 
            // Создание анонимного объекта: 
            new MyClass("Второй");
            // Новый объект:
            A = new MyClass("Третий");
            // Вызов статического метода: 
            maker("Четвертый");
            // Новый объект:
            A = new MyClass("Пятый");
        }
    }
}
Архив проекта можно взять здесь.

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


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


В конце приведенной программы отсутствует задержка. При использовании клавиши F5, то есть запуске программы в режиме отладки, консольное окно после завершения программы может быть автоматически закрыто. Чтобы увидеть результат, приведенный на рисунке 1, нужно запустить приложение не в режиме отладки, нажав комбинацию клавиш Ctrl + F5.

    Мы описываем класс MyClass, и в этом классе есть закрытое текстовое поле name. Конструктор у класса всего один. Аргументом конструктору передается текстовое значение, которое присваивается полю name. После присваивания значения полю name командой

  Console.WriteLine("Создан объект \"{0}\"", name);
в консольное окно выводится сообщение о том, что создан новый объект. Сообщение содержит значение поля name созданного объекта.


Один факт создания объекта означает, что в консольном окне появляется сообщение со значением закрытого текстового поля этого объекта. Проще говоря, когда с использованием оператора new создается объект класса MyClass, в консольном окне появляется сообщение. Все это - благодаря конструктору, в котором есть соответствующая команда.

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


    Еще в классе есть деструктор. В теле деструктора всего одна команда

  Console.WriteLine("Удален объект \"{0}\"", name);   , 
которой в консольное окно выводится сообщение об удалении объекта и значении поля name этого объекта.


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

    В главном классе программы кроме метода Main() описан еще и статический метод maker(). У метода есть текстовый аргумент (обозначен как txt). В теле метода всего одна команда

  new MyClass(txt);   , 
которой создается объект класса MyClass. Пикантность ситуации в том, что ссылка на созданный объект не записывается в объектную переменную. Получается, что объект создается, но нет переменной, через которую можно было бы получить доступ к этому объекту. Такие объекты обычно называют анонимными.


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

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

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

  MyClass A = new MyClass("Первый"); 
создается первый объект. Вследствие вызова конструктора при выполнении этой команды в консольном окне появляется сообщение Создан объект "Первый". После этого командой
  new MyClass("Второй");
создается второй объект, и в консольном окне появляется сообщение Создан объект "Второй". Созданный объект анонимный, поскольку ссылка на него в объектную переменную нс записывается. Раз так, то получается, что программа не содержит переменных со ссылками на созданный объект, и он становится кандидатом на удаление. Начиная с этого момента, в консольном окне потенциально может появиться сообщение об удалении объекта (но в данном случае пока не появляется).

    Командой

  A = new MyClass("Третий");
создается третий объект (при создании объекта в консоли появляется сообщение Создан объект "Третий"), и ссылка на него записывается в переменную А. Раньше в эту переменную была записана ссылка на первый объект. Теперь переменная ссылается на третий объект. Следовательно, на первый объект ссылок в программе не осталось. Поэтому первый объект также становится кандидатом на удаление и может быть удален системой "сборки мусора".

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

    Наконец, последней командой

  A = new MyClass("Пятый");
в главном методе создается еще одни (пятый по счету) объект (в консоли появляется сообщение Создан объект "Пятый"), и ссылка на него записывается в переменную А. До этого переменная А ссылалась на третий объект. Следовательно, третий объект подлежит удалению, поскольку на него в программе ссылок нет.

    На последний, пятый объект, в программе ссылка есть (записана в переменную А). Но программа завершает работу. А при завершении выполнения программы из памяти удаляются все переменные и объекты. 11оэтому пятый объект также должен быть удален. В итоге мы получаем, что все пять созданных объектов класса MyClass должны быть удалены. И они начинают удаляться. Как видно из результата выполнения программы, первым удаляется объект "Пятый". Затем удаляется объект "Первый", затем "Четвертый", "Третий" и, наконец, "Второй". Здесь еще раз подчеркнем, что удалением объектов из памяти занимается система "сборки мусора", поэтому нельзя однозначно предугадать, когда именно объекты будут удалены. Можно быть уверенным лишь в том, что это произойдет.

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




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