Поделиться через


Время существования: создание и уничтожение объектов (Visual Basic)

Объект как экземпляр класса создается с помощью ключевого слова New.Задачи инициализации перед использованием обычно должны выполняться для новых объектов.При инициализации выполняются следующие действия: открытие файлов, подключение к базам данных, чтение разделов реестра.Visual Basic контролирует инициализацию новых объектов с помощью процедур, называемых конструкторами (специальные методы, позволяющие контролировать инициализацию).

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

Использование конструкторов и деструкторов

Конструкторы и деструкторы контролируют создание и удаление объектов.В Visual Basic процедуры Sub New и Sub Finalize инициализируют и уничтожают объекты. Эти процедуры заменяют методы Class_Initialize и Class_Terminate, использовавшиеся в Visual Basic 6.0 и более ранних версий.

hks5e2k6.collapse_all(ru-ru,VS.110).gifКонструктор Sub New

Конструктор Sub New можно запустить только один раз при создании класса.Он может быть вызван явным образом только в первой строке кода другого конструктора того же или производного класса.Следовательно, код метода Sub New всегда выполняется раньше остальных частей кода в классе.Visual Basic 2005 и более поздние версии неявно создают конструктор Sub New во время выполнения, если явно не определена процедура Sub New для создания класса.

Чтобы создать конструктор для класса, нужно создать процедуру Sub New в любом месте в определении класса.Для создания конструктора с параметрами нужно задать имена и типы данных аргументов для Sub New аналогично назначению аргументов для любой другой процедуры, как в следующем примере:

Sub New(ByVal s As String)

Конструкторы часто перегружаются, как в следующем примере.

Sub New(ByVal s As String, i As Integer)

При определении класса, производного от другого класса, первая строка конструктора должна являться вызовом конструктора базового класса, если только базовый класс не имеет доступный конструктор, не использующий параметры.Пример вызова базового класса, содержащего вышеупомянутый конструктор: MyBase.New(s).В противном случае MyBase.New является необязательным и среда выполнения Visual Basic вызывает его неявно.

После создания кода для вызова конструктора родительского объекта можно добавить в процедуру Sub New любой дополнительный код инициализации.Sub New может принимать аргументы при вызове в качестве параметризованного конструктора.Эти параметры передаются из процедуры, вызывающей конструктор. Например, Dim AnObject As New ThisClass(X).

hks5e2k6.collapse_all(ru-ru,VS.110).gifПроцедура Sub Finalize

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

ПримечаниеПримечание

Сборщик мусора в CLR не уничтожает (и не может уничтожить) неуправляемые объекты — объекты, которые выполняются операционными системами напрямую, вне среды CLR.Это вызвано тем, что различные неуправляемые объекты должны быть уничтожены различными способами.Эти сведения непосредственно не связаны с неуправляемыми объектами; они содержатся в документации по объекту.Класс, который использует неуправляемые объекты, должен уничтожать их в своем методе Finalize.

Деструктор Finalize является защищенным методом и может быть вызван только из производного класса или из того класса, к которому он принадлежит.Не следует явным образом вызывать Finalize вне реализации Finalize производного класса, поскольку система автоматически вызывает Finalize при удалении объекта.

В отличие от события Class_Terminate, которое выполняется сразу же после присвоения объекту значения Nothing, между выходом объекта из области и вызовом Visual Basic деструктора Finalize обычно происходит задержка.В Visual Basic 2005 и в последующих версиях разрешен второй вид деструктора — Dispose, который можно явно вызывать в любое время, чтобы немедленно освободить ресурсы.

ПримечаниеПримечание

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

hks5e2k6.collapse_all(ru-ru,VS.110).gifРабота методов New и Finalize в иерархии классов

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

При создании экземпляра производного класса сначала выполняется конструктор Sub New базового класса, а затем выполняются конструкторы в производных классах.Это происходит, потому что первая строка кода в конструкторе Sub New использует синтаксис MyBase.New() для вызова конструктора класса, стоящего непосредственно над заданным в иерархии классов.Затем в иерархии классов для каждого класса вызывается конструктор Sub New, пока не будет достигнут конструктор базового класса.На этом этапе выполняется код в конструкторе базового класса, а затем выполняется код в каждом конструкторе во всех производных классах. В производных классах, дальше всего отстоящих от базового, код выполняется в последнюю очередь.

Конструкторы и наследование

Когда объект больше не нужен, среда CLR перед очисткой памяти вызывает метод Finalize для этого объекта.Метод Finalize называется деструктором (destructor), так как он выполняет задачи по очистке, такие как сохранение данных о состоянии, закрытие файлов и подключений к базам данных и другие задачи, которые необходимо выполнить до освобождения объекта.

Конструкторы и наследование 2

Интерфейс IDisposable

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

Для дополнения сборки мусора классы могут предоставить механизм активного управления системными ресурсами, если они реализуют интерфейс IDisposable.IDisposable имеет один метод — Dispose, который клиенты могут вызывать после завершения использования объекта.Можно использовать метод Dispose для немедленного освобождения ресурсов и выполнения задач, например для закрытия файлов и подключений к базе данных.В отличие от деструктора Finalize метод Dispose не вызывается автоматически.Для немедленного освобождения ресурсов клиенты класса должны вызывать Dispose явным образом.

hks5e2k6.collapse_all(ru-ru,VS.110).gifРеализация IDisposable

Класс, реализующий интерфейс IDisposable, должен включать эти фрагменты кода:

  • Поле для отслеживания уничтожения объекта:

    Protected disposed As Boolean = False
    
  • Перегрузка Dispose, которая освобождает ресурсы класса.Этот метод должен вызываться методами базового класса Dispose и Finalize:

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • Реализация Dispose, содержащая только следующий код:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Переопределенный метод Finalize, содержащий только следующий код:

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

hks5e2k6.collapse_all(ru-ru,VS.110).gifНаследование от класса, реализующего интерфейс IDisposable

Класс, производный от базового класса, реализующего интерфейс IDisposable, не должен переопределять какой-либо из базовых методов, если только он не использует дополнительные ресурсы, которые необходимо освободить.В этой ситуации производный класс должен переопределять метод Dispose(disposing) базового класса для освобождения своих ресурсов.Это переопределение должно вызывать метод Dispose(disposing) базового класса.

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

Не следует переопределять методы базового класса Dispose и Finalize в производном классе.При вызове этих методов из экземпляра производного класса реализация этих методов базового класса вызовет переопределенный метод Dispose(disposing) производного класса.

Сборка мусора и деструктор Finalize

.NET Framework использует систему сборки мусора с трассировкой ссылок для периодического освобождения неиспользуемых ресурсов.В Visual Basic 6.0 и более ранних версиях для управления ресурсами используется другая система под названием подсчет ссылок.Несмотря на то, что обе системы выполняют одинаковые функции автоматически, существует несколько важных различий.

CLR периодически удаляет объекты, если система определяет, что эти объекты больше не нужны.Если ресурсов системы не хватает, объекты освобождаются быстрее.Существующая задержка между выходом объекта из области действия и его освобождением CLR означает, что, в отличие от Visual Basic 6.0 и боллее ранних версий, невозможно точно определить момент удаления объекта.В таком случае считается, что объекты имеют неопределенное время существования.Если учитывать тот факт, что деструктор Finalize может выполняться не сразу после удаления объекта из контекста, в большинстве случаев неопределенное время существования никак не влияет на способ написания приложений.

Другое различие между системами сборки мусора состоит в использовании ключевого слова Nothing.Чтобы воспользоваться преимуществами подсчета ссылок в Visual Basic 6.0 и более ранних версиях, программисты иногда назначали Nothing переменным объекта для освобождения ссылок этих переменных.Ресурсы объекта освобождались немедленно, если переменная содержала последнюю ссылку на объект.В последних версиях Visual Basic данная процедура также может использоваться: при ее выполнении объект, на который существует ссылка, никогда не освобождает ресурсы мгновенно.Чтобы немедленно освободить ресурсы, используйте метод Dispose объекта, если он доступен.Ключевое слово Nothing следует задавать переменной только в том случае, если ее время жизни велико по сравнению с временем, за которое сборщик мусора обнаруживает объекты без родителя.

См. также

Ссылки

Оператор New (Visual Basic)

Dispose

Nothing (Visual Basic)

Основные понятия

Инициализация и прекращение работы компонентов

Методы "Finalize" и деструкторы