Оператор Использовать - гарантированное завершение объекта — различия между версиями

Материал из ТХАБ.РФ
Перейти к: навигация, поиск
(Новая страница: «Многие объекты так устроены, что в конце работы с ними, их надо условно "выключить", т.е. ко…»)
 
м
Строка 1: Строка 1:
 
Многие объекты так устроены, что в конце работы с ними, их надо условно "выключить", т.е. корректно завершить их работу. Это позволит освободить занятые объектом физические устройства и очистить память компьютера. Если забыть это сделать, то программа или даже компьютер могут перестать нормально работать. Оператор [[Оператор Использовать - гарантированное завершение объекта|Использовать]] позволяет гарантированно вызвать метод-завершитель объекта.
 
Многие объекты так устроены, что в конце работы с ними, их надо условно "выключить", т.е. корректно завершить их работу. Это позволит освободить занятые объектом физические устройства и очистить память компьютера. Если забыть это сделать, то программа или даже компьютер могут перестать нормально работать. Оператор [[Оператор Использовать - гарантированное завершение объекта|Использовать]] позволяет гарантированно вызвать метод-завершитель объекта.
  
Уходя не забудьте выключить все работающие объекты.
+
В связи с тем, что язык программирования Перфолента.Net построен на базе среды исполнения .Net, в нем существуют операторы и некоторые другие возможности присущие этой среде.
В связи с тем, что язык программирования Перфолента.Net построен на базе технологии .Net, в нем существуют операторы и некоторые другие возможности присущие этой среде.
+
  
+
== Погрузимся в глубины .Net ==
 
+
Погрузимся в глубины .Net.
+
  
 
Если класс написан на языке Перфолента и использует только типы, определенные в языке, то он относится к коду, управляемому CLR (Common Language Runtime – общеязыковая среда выполнения .Net) и все объекты, созданные на основании этого класса, будут удалены из памяти компьютера сборщиком мусора, когда на них не останется ссылок из других объектов программы. Это значит, что программист может не заботится об очистке памяти компьютера от не нужных объектов - всё сделает сборщик мусора.
 
Если класс написан на языке Перфолента и использует только типы, определенные в языке, то он относится к коду, управляемому CLR (Common Language Runtime – общеязыковая среда выполнения .Net) и все объекты, созданные на основании этого класса, будут удалены из памяти компьютера сборщиком мусора, когда на них не останется ссылок из других объектов программы. Это значит, что программист может не заботится об очистке памяти компьютера от не нужных объектов - всё сделает сборщик мусора.
  
Однако, в .Net многие объекты для своей работы используют разнообразные НЕ управляемые ресурсы операционной системы, например, файлы, сетевые подключения, дескрипторы картинок и т.д. Разработчик такого объекта должен позаботится о том, чтобы как можно скорее освободить занятые ресурсы, если объект больше не нужен программе. Казалось бы, для этой цели идеально подходит метод объекта Деструктор, который можно определить в любом классе. Однако, Деструктор объекта будет вызван не сразу, когда на объект больше не осталось ссылок, а через некоторое время, когда сборщик мусора решит заняться очисткой памяти от не нужных более объектов. Более того, согласно документации, в некоторых случаях Деструктор может быть не вызван вовсе, например, при аварийном завершении программы.  
+
Однако, в .Net многие объекты для своей работы используют разнообразные НЕ управляемые ресурсы операционной системы, например, файлы, сетевые подключения, дескрипторы картинок и т.д. Разработчик такого объекта должен позаботится о том, чтобы как можно скорее освободить занятые ресурсы, если объект больше не нужен программе. Казалось бы, для этой цели идеально подходит метод объекта [[Деструктор]], который можно определить в любом классе. Однако, Деструктор объекта будет вызван не сразу, когда на объект больше не осталось ссылок, а через некоторое время, когда сборщик мусора решит заняться очисткой памяти от не нужных более объектов. Более того, согласно документации, в некоторых случаях Деструктор может быть не вызван вовсе, например, при аварийном завершении программы.  
  
 
Что же делать разработчику, чтобы гарантировано освободить ресурсы? Лучше всего, как только объект стал не нужен, вручную вызвать метод объекта освобождающий занятые им ресурсы. Именно так и рассуждали разработчики .Net.
 
Что же делать разработчику, чтобы гарантировано освободить ресурсы? Лучше всего, как только объект стал не нужен, вручную вызвать метод объекта освобождающий занятые им ресурсы. Именно так и рассуждали разработчики .Net.
  
В .Net предусмотрен специальный интерфейс IDisposable, у которого есть метод Dispose. Разработчик объекта должен реализовать этот интерфейс и описать в методе Dispose алгоритм освобождения ресурсов, а программист использующий объект должен вызвать метод Dispose, как только объект больше не нужен программе. В языке Перфолента для этих же целей может быть использован метод Завершитель.
+
В .Net предусмотрен специальный [[интерфейс]] [[IDisposable]], у которого есть метод [[Dispose]]. Разработчик объекта должен реализовать этот интерфейс и описать в методе Dispose алгоритм освобождения ресурсов, а программист использующий объект должен вызвать метод Dispose, как только объект больше не нужен программе. В языке Перфолента для этих же целей может быть использован метод [[Завершитель]].
 
+
+
 
+
Вернемся к Перфоленте.
+
  
В языке Перфолента разработчик класса, должен определить метод Завершитель, для освобождения управляемых ресурсов, и метод Деструктор для освобождения не управляемых ресурсов. Компилятор языка Перфолента автоматически включит необходимую реализацию интерфейса IDisposable и методы Dispose и Finalize, если у класса определен хотя бы один из методов Завершитель или Деструктор. Подробнее об этих методах можно почитать в статье «Конструируем класс. Завершители и Деструкторы».
+
=== Вернемся к Перфоленте ===
  
+
В языке Перфолента разработчик класса, должен определить метод [[Завершитель]], для освобождения управляемых ресурсов, и метод [[Деструктор]] для освобождения не управляемых ресурсов. Компилятор языка Перфолента автоматически включит необходимую реализацию интерфейса [[IDisposable]] и методы [[Dispose]] и [[Finalize]], если у класса определен хотя бы один из методов [[Завершитель]] или [[Деструктор]]. Подробнее об этих методах можно почитать в статье «[[Конструируем класс. Завершители и Деструкторы]]».
  
Гарантированное завершение.
+
=== Гарантированное завершение ===
  
Если у объекта есть метод Завершитель или вручную реализован интерфейс IDisposable, то программист может в любой момент вызвать процедуру освобождения ресурсов, занятых этим объектом с помощью оператора ВызватьЗавершитель, и на первый взгляд кажется, что этого достаточно. Однако, уверен ли программист, что программа всегда дойдет до того места, где этот вызов определен? А если случится исключение? А если программист со временем забудет, что в этом коде используются ресурсы, требующие обязательного освобождения, или код будет править другой программист и в коде появится не предусмотренный условный выход из процедуры? Ресурс не будет освобожден?
+
Если у объекта есть метод [[Завершитель]] или вручную реализован интерфейс [[IDisposable]], то программист может в любой момент вызвать процедуру освобождения ресурсов, занятых этим объектом с помощью оператора ВызватьЗавершитель, и на первый взгляд кажется, что этого достаточно. Однако, уверен ли программист, что программа всегда дойдет до того места, где этот вызов определен? А если случится исключение? А если программист со временем забудет, что в этом коде используются ресурсы, требующие обязательного освобождения, или код будет править другой программист и в коде появится не предусмотренный условный выход из процедуры? Ресурс не будет освобожден?
  
 
Да, такое возможно. А как же этого избежать? Способы есть. Можно, например, применить оператор Попытка и в секции Завершение освободить ресурсы с помощью оператора ВызватьЗавершитель. Это сработает!
 
Да, такое возможно. А как же этого избежать? Способы есть. Можно, например, применить оператор Попытка и в секции Завершение освободить ресурсы с помощью оператора ВызватьЗавершитель. Это сработает!
Строка 32: Строка 25:
 
Однако, есть и более удобный оператор для этой цели…
 
Однако, есть и более удобный оператор для этой цели…
  
+
===Оператор «Использовать» ===
  
Оператор «Использовать».
+
В языке Перфолента.Net существует специальный [[блочный оператор]] Использовать, который гарантирует автоматический вызов Завершителя объекта, вне зависимости от того, каким способом осуществлен выход из алгоритма. Этот оператор является [[синтаксическим сахаром]], объединяя синтаксис создания объектов, ресурсы которых необходимо освобождать и автоматическое гарантированное их освобождение.
 
+
В языке Перфолента.Net существует специальный блочный оператор Использовать, который гарантирует автоматический вызов завершителя объекта, вне зависимости от того, каким способом осуществлен выход из алгоритма. Этот оператор является синтаксическим сахаром, объединяя синтаксис создания объектов, ресурсы которых необходимо освобождать и автоматическое гарантированное их освобождение.
+
  
 
Рассмотрим синтаксис оператора Использовать:
 
Рассмотрим синтаксис оператора Использовать:
  
Использовать Ф1 тип ЗаписьТекста = Новый ЗаписьТекста("log1.txt")
+
Использовать Ф1 тип ЗаписьТекста = Новый ЗаписьТекста("log1.txt")
 
             Ф1.Записать("Запись в файл 1")
 
             Ф1.Записать("Запись в файл 1")
КонецИспользовать
+
КонецИспользовать
  
Переменная Ф1 определяется прямо в операторе Использовать по аналогии с операторами Для и Для Каждого. Этой переменной присваивается объект, ресурсы которого будут освобождены при выходе из блока любым способом.
+
Переменная Ф1 определяется прямо в операторе Использовать по аналогии с операторами [[Для]] и [[Для Каждого]]. Этой переменной присваивается объект, ресурсы которого будут освобождены при выходе из блока любым способом.
  
Тип переменной Ф1 должен допускать завершение, т.е. иметь метод Завершитель или реализацию интерфейса IDisposable.
+
Тип переменной Ф1 должен допускать завершение, т.е. иметь метод [[Завершитель]] или реализацию интерфейса [[IDisposable]].
  
Умнику на заметку: Как и при определении переменных в операторе Перем, тип переменной в операторе Использовать можно не задавать, если присутствует выражение создающее объект заданного типа.
+
'''На заметку:''' Как и при определении переменных в операторе [[Перем]], тип переменной в операторе [[Использовать]] можно не задавать, если присутствует выражение создающее объект заданного типа.
  
 
Допускается использование ранее определенных переменных, однако, в этом случае прежде, чем обращаться к объекту, необходимо убедиться, что он существует:
 
Допускается использование ранее определенных переменных, однако, в этом случае прежде, чем обращаться к объекту, необходимо убедиться, что он существует:
  
Перем Ф1 тип ЗаписьТекста
+
Перем Ф1 тип ЗаписьТекста
// … … … тут какой-то код
+
// … … … тут какой-то код
Использовать Ф1
+
Использовать Ф1
 
             //объект Ф1 надо инициализировать, если он не определен
 
             //объект Ф1 надо инициализировать, если он не определен
 
             Ф1 = ЕслиНеопределено(Ф1, Новый ЗаписьТекста("log1.txt"))
 
             Ф1 = ЕслиНеопределено(Ф1, Новый ЗаписьТекста("log1.txt"))
Строка 62: Строка 53:
 
             Ф1 ??= Новый ЗаписьТекста("log1.txt")
 
             Ф1 ??= Новый ЗаписьТекста("log1.txt")
 
             Ф1.Записать("Запись в файл 1")
 
             Ф1.Записать("Запись в файл 1")
КонецИспользовать
+
КонецИспользовать
  
 
В операторе Использовать возможно определение и создание сразу нескольких объектов, каждый из которых будет освобожден при выходе из блока Использовать:
 
В операторе Использовать возможно определение и создание сразу нескольких объектов, каждый из которых будет освобожден при выходе из блока Использовать:
  
Использовать Ф1 = Новый ЗаписьТекста("log1.txt"),
+
Использовать Ф1 = Новый ЗаписьТекста("log1.txt"),
 
                           Ф2 = Новый ЗаписьТекста("log2.txt"),
 
                           Ф2 = Новый ЗаписьТекста("log2.txt"),
 
                           Ф3 = Новый ЗаписьТекста("log3.txt")
 
                           Ф3 = Новый ЗаписьТекста("log3.txt")
Строка 72: Строка 63:
 
             Ф2.Записать("Запись в файл 2")
 
             Ф2.Записать("Запись в файл 2")
 
             Ф3.Записать("Запись в файл 3")
 
             Ф3.Записать("Запись в файл 3")
КонецИспользовать
+
КонецИспользовать
  
+
=== [[Секция Исключение]] ===
  
Секция Исключение.
+
Обычно, алгоритм находящийся внутри блока Использовать можно рассматривать как единое целое. Это значит, что при возникновении ошибки продолжать его выполнение невозможно. Если в случае возникновения ошибки необходимо выполнить какие-либо действия, направленные на исправление ошибочной ситуации, можно применить не обязательную секцию [[Исключение]].
  
Обычно, алгоритм находящийся внутри блока Использовать можно рассматривать как единое целое. Это значит, что при возникновении ошибки продолжать его выполнение невозможно. Если в случае возникновения ошибки необходимо выполнить какие-либо действия, направленные на исправление ошибочной ситуации, можно применить не обязательную секцию Исключение.
+
Использовать Ф1 = Новый ЗаписьТекста("log1.txt")
 
+
Использовать Ф1 = Новый ЗаписьТекста("log1.txt")
+
 
             Ф1.Записать("Запись в файл 1")
 
             Ф1.Записать("Запись в файл 1")
Исключение Ош
+
Исключение Ош
 
             ВыводСтроки "Ошибка: "+Ош.ОписаниеОшибки()
 
             ВыводСтроки "Ошибка: "+Ош.ОписаниеОшибки()
КонецИспользовать
+
КонецИспользовать
  
Умнику на заметку: ВАЖНО! Оператор Попытка ловит ошибку всегда, а оператор Использовать ловит ошибку только тогда, когда задана секция Исключение!!!
+
'''На заметку: ВАЖНО!''' Оператор [[Попытка]] ловит ошибку всегда, а оператор [[Использовать]] ловит ошибку только тогда, когда задана [[секция Исключение]]!!!
  
+
=== [[Секция Завершение]] ===
  
Секция Завершение.
+
[[Оператор Использовать]] автоматически завершает объекты при выходе из блока. Однако, иногда необходимо выполнить дополнительные завершающие действия, например, послать в линию особый сигнал завершения, прежде, чем линия будет закрыта. В этом случае можно использовать не обязательную секцию Завершение:
  
Оператор Использовать автоматически завершает объекты при выходе из блока. Однако, иногда необходимо выполнить дополнительные завершающие действия, например, послать в линию особый сигнал завершения, прежде, чем линия будет закрыта. В этом случае можно использовать не обязательную секцию Завершение:
+
Использовать Линия = Новый ЛинияПередачиДанных
 
+
Использовать Линия = Новый ЛинияПередачиДанных
+
 
             Линия.Записать("Обычные данные")
 
             Линия.Записать("Обычные данные")
Завершение
+
Завершение
 
             Линия.ПодписатьДанные("Моя подпись")
 
             Линия.ПодписатьДанные("Моя подпись")
КонецИспользовать
+
КонецИспользовать
  
+
=== Используем все секции ===
 
+
Используем все секции.
+
  
 
В том случае, когда используются все секции, оператор Использовать выглядит так:
 
В том случае, когда используются все секции, оператор Использовать выглядит так:
  
Использовать МойОбъект тип ТипМоегоОбъекта = ВыражениеИнициализацииОбъекта
+
Использовать МойОбъект тип ТипМоегоОбъекта = ВыражениеИнициализацииОбъекта
 
             //тут работаем с объектом, на который ссылается переменная МойОбъект
 
             //тут работаем с объектом, на который ссылается переменная МойОбъект
Исключение Ош
+
Исключение Ош
 
             //тут обрабатываем ошибку, возникшую при работе с объектом
 
             //тут обрабатываем ошибку, возникшую при работе с объектом
Завершение
+
Завершение
 
             //тут, выполняем дополнительные завершающие действия с объектом
 
             //тут, выполняем дополнительные завершающие действия с объектом
 
             // перед его завершением
 
             // перед его завершением
КонецИспользовать
+
  КонецИспользовать
 
+
   
+
  
Оператор «Исп». Сокращенная форма оператора «Использовать»
+
=== Оператор «Исп». Сокращенная форма оператора «Использовать» ===
  
 
В некоторых случаях блочный оператор Использовать сильно увеличивает вложенность блоков, что приводит к ухудшению читабельности программы. В таких случаях можно применять его сокращенную форму Исп.
 
В некоторых случаях блочный оператор Использовать сильно увеличивает вложенность блоков, что приводит к ухудшению читабельности программы. В таких случаях можно применять его сокращенную форму Исп.
Строка 123: Строка 106:
 
Так же, как и оператор Использовать, оператор Исп гарантирует автоматический вызов завершителя объекта, вне зависимости от того, каким способом осуществлен выход из алгоритма.
 
Так же, как и оператор Использовать, оператор Исп гарантирует автоматический вызов завершителя объекта, вне зависимости от того, каким способом осуществлен выход из алгоритма.
  
Оператор Исп по-прежнему остаётся блочным оператором, однако конец блока Исп компилятор определяет автоматически. Конец блока оператора Исп находится либо в конце того блока, в который он вложен, либо в конце метода, если оператор Исп не вложен в другие блоки.
+
Оператор Исп по-прежнему остаётся блочным оператором, однако '''конец блока Исп компилятор определяет автоматически.''' Конец блока оператора Исп находится либо в конце того блока, в который он вложен, либо в конце метода, если оператор Исп не вложен в другие блоки.
  
У оператора Исп нет секций Исключение и Завершение, а значит он не перехватывает ошибки и не позволяет выполнить дополнительные завершающие действия.
+
'''У оператора Исп нет секций [[Исключение]] и [[Завершение]]''', а значит он не перехватывает ошибки и не позволяет выполнить дополнительные завершающие действия.
  
Рассмотрим два случая, когда оператор Исп находится в блоке Если и когда он не вложен в какой-либо блок.
+
Рассмотрим 2 случая, когда оператор Исп находится в блоке Если и когда он не вложен в какой-либо блок.
  
Случай 1.
+
==== Случай 1 ====
  
Процедура Старт
+
Процедура Старт
 
             Если НадоПередатьДанные
 
             Если НадоПередатьДанные
 
                         // оператор ИСП действует до конца окружающего его блока
 
                         // оператор ИСП действует до конца окружающего его блока
Строка 142: Строка 125:
 
                         // тут закончится блок оператора ИСП
 
                         // тут закончится блок оператора ИСП
 
             КонецЕсли
 
             КонецЕсли
КонецПроцедуры
+
КонецПроцедуры
  
Случай 2.
+
==== Случай 2 ====
  
Процедура Старт
+
Процедура Старт
 
             // оператор ИСП действует до конца метода
 
             // оператор ИСП действует до конца метода
 
             // т.к. он не вложен ни в один блок
 
             // т.к. он не вложен ни в один блок
Строка 158: Строка 141:
 
             // вот тут, в конце метода будет освобождена переменная Линия
 
             // вот тут, в конце метода будет освобождена переменная Линия
 
             // тут закончится блок оператора ИСП
 
             // тут закончится блок оператора ИСП
КонецПроцедуры
+
КонецПроцедуры
  
Умнику на заметку: ВАЖНО! Переменная, объявленная в операторе Исп действительна до конца метода, однако, в конце блока Исп для неё будет вызван Завершитель и она получит значение Неопределено!!! Это не помешает Вам инициализировать и использовать её снова ниже по коду метода.
+
'''На заметку: ВАЖНО!''' Переменная, объявленная в операторе Исп действительна до конца метода, однако, в конце блока Исп для неё будет вызван Завершитель и она получит значение [[Неопределено]]!!! Это не помешает Вам инициализировать и использовать её снова ниже по коду метода.
  
+
'''Вывод:''' [[Оператор Использовать]] и его '''сокращенная форма Исп''' позволяют автоматически гарантированно освобождать ресурсы, занятые заданным объектом. Оператор Использовать при необходимости позволяет перехватывать возникающие при работе с объектом ошибки и/или выполнять дополнительные завершающие действия перед освобождением ресурсов и окончательным завершением работы объекта.
  
+
Сергей Рогаткин 27.06.2021 13:12
  
'''Вывод:''' Оператор Использовать и его сокращенная форма Исп позволяют автоматически гарантированно освобождать ресурсы, занятые заданным объектом. Оператор Использовать при необходимости позволяет перехватывать возникающие при работе с объектом ошибки и/или выполнять дополнительные завершающие действия перед освобождением ресурсов и окончательным завершением работы объекта.
+
== См. также ==
 +
* [[Объектно-ориентированное программирование на языке Перфолента.NET]]
  
Сергей Рогаткин 27.06.2021 13:12
+
== Ссылки ==
 +
* https://web.archive.org/web/20220606070941/http://promcod.com.ua/Article.asp?code=20210627131239088905 Первоисточник Веб Архив
  
 
[[Категория:Перфолента.NET]]
 
[[Категория:Перфолента.NET]]
 
[[Категория:Описание языка Перфолента.NET]]
 
[[Категория:Описание языка Перфолента.NET]]

Версия 20:11, 8 июня 2023

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

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

Погрузимся в глубины .Net

Если класс написан на языке Перфолента и использует только типы, определенные в языке, то он относится к коду, управляемому CLR (Common Language Runtime – общеязыковая среда выполнения .Net) и все объекты, созданные на основании этого класса, будут удалены из памяти компьютера сборщиком мусора, когда на них не останется ссылок из других объектов программы. Это значит, что программист может не заботится об очистке памяти компьютера от не нужных объектов - всё сделает сборщик мусора.

Однако, в .Net многие объекты для своей работы используют разнообразные НЕ управляемые ресурсы операционной системы, например, файлы, сетевые подключения, дескрипторы картинок и т.д. Разработчик такого объекта должен позаботится о том, чтобы как можно скорее освободить занятые ресурсы, если объект больше не нужен программе. Казалось бы, для этой цели идеально подходит метод объекта Деструктор, который можно определить в любом классе. Однако, Деструктор объекта будет вызван не сразу, когда на объект больше не осталось ссылок, а через некоторое время, когда сборщик мусора решит заняться очисткой памяти от не нужных более объектов. Более того, согласно документации, в некоторых случаях Деструктор может быть не вызван вовсе, например, при аварийном завершении программы.

Что же делать разработчику, чтобы гарантировано освободить ресурсы? Лучше всего, как только объект стал не нужен, вручную вызвать метод объекта освобождающий занятые им ресурсы. Именно так и рассуждали разработчики .Net.

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

Вернемся к Перфоленте

В языке Перфолента разработчик класса, должен определить метод Завершитель, для освобождения управляемых ресурсов, и метод Деструктор для освобождения не управляемых ресурсов. Компилятор языка Перфолента автоматически включит необходимую реализацию интерфейса IDisposable и методы Dispose и Finalize, если у класса определен хотя бы один из методов Завершитель или Деструктор. Подробнее об этих методах можно почитать в статье «Конструируем класс. Завершители и Деструкторы».

Гарантированное завершение

Если у объекта есть метод Завершитель или вручную реализован интерфейс IDisposable, то программист может в любой момент вызвать процедуру освобождения ресурсов, занятых этим объектом с помощью оператора ВызватьЗавершитель, и на первый взгляд кажется, что этого достаточно. Однако, уверен ли программист, что программа всегда дойдет до того места, где этот вызов определен? А если случится исключение? А если программист со временем забудет, что в этом коде используются ресурсы, требующие обязательного освобождения, или код будет править другой программист и в коде появится не предусмотренный условный выход из процедуры? Ресурс не будет освобожден?

Да, такое возможно. А как же этого избежать? Способы есть. Можно, например, применить оператор Попытка и в секции Завершение освободить ресурсы с помощью оператора ВызватьЗавершитель. Это сработает!

Однако, есть и более удобный оператор для этой цели…

Оператор «Использовать»

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

Рассмотрим синтаксис оператора Использовать:

Использовать Ф1 тип ЗаписьТекста = Новый ЗаписьТекста("log1.txt")
           Ф1.Записать("Запись в файл 1")
КонецИспользовать

Переменная Ф1 определяется прямо в операторе Использовать по аналогии с операторами Для и Для Каждого. Этой переменной присваивается объект, ресурсы которого будут освобождены при выходе из блока любым способом.

Тип переменной Ф1 должен допускать завершение, т.е. иметь метод Завершитель или реализацию интерфейса IDisposable.

На заметку: Как и при определении переменных в операторе Перем, тип переменной в операторе Использовать можно не задавать, если присутствует выражение создающее объект заданного типа.

Допускается использование ранее определенных переменных, однако, в этом случае прежде, чем обращаться к объекту, необходимо убедиться, что он существует:

Перем Ф1 тип ЗаписьТекста
// … … … тут какой-то код
Использовать Ф1
           //объект Ф1 надо инициализировать, если он не определен
           Ф1 = ЕслиНеопределено(Ф1, Новый ЗаписьТекста("log1.txt"))
           // или так (операция ?? аналогична функции ЕслиНеопределено)
           Ф1 = Ф1 ?? Новый ЗаписьТекста("log1.txt")
           //или ещё короче с помощью комбинированного оператора ??=
           Ф1 ??= Новый ЗаписьТекста("log1.txt")
           Ф1.Записать("Запись в файл 1")
КонецИспользовать

В операторе Использовать возможно определение и создание сразу нескольких объектов, каждый из которых будет освобожден при выходе из блока Использовать:

Использовать Ф1 = Новый ЗаписьТекста("log1.txt"),
                          Ф2 = Новый ЗаписьТекста("log2.txt"),
                          Ф3 = Новый ЗаписьТекста("log3.txt")
           Ф1.Записать("Запись в файл 1")
           Ф2.Записать("Запись в файл 2")
           Ф3.Записать("Запись в файл 3")
КонецИспользовать

Секция Исключение

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

Использовать Ф1 = Новый ЗаписьТекста("log1.txt")
           Ф1.Записать("Запись в файл 1")
Исключение Ош
           ВыводСтроки "Ошибка: "+Ош.ОписаниеОшибки()
КонецИспользовать

На заметку: ВАЖНО! Оператор Попытка ловит ошибку всегда, а оператор Использовать ловит ошибку только тогда, когда задана секция Исключение!!!

Секция Завершение

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

Использовать Линия = Новый ЛинияПередачиДанных
           Линия.Записать("Обычные данные")
Завершение
           Линия.ПодписатьДанные("Моя подпись")
КонецИспользовать

Используем все секции

В том случае, когда используются все секции, оператор Использовать выглядит так:

Использовать МойОбъект тип ТипМоегоОбъекта = ВыражениеИнициализацииОбъекта
           //тут работаем с объектом, на который ссылается переменная МойОбъект
Исключение Ош
           //тут обрабатываем ошибку, возникшую при работе с объектом
Завершение
           //тут, выполняем дополнительные завершающие действия с объектом
           // перед его завершением
КонецИспользовать

Оператор «Исп». Сокращенная форма оператора «Использовать»

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

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

Оператор Исп по-прежнему остаётся блочным оператором, однако конец блока Исп компилятор определяет автоматически. Конец блока оператора Исп находится либо в конце того блока, в который он вложен, либо в конце метода, если оператор Исп не вложен в другие блоки.

У оператора Исп нет секций Исключение и Завершение, а значит он не перехватывает ошибки и не позволяет выполнить дополнительные завершающие действия.

Рассмотрим 2 случая, когда оператор Исп находится в блоке Если и когда он не вложен в какой-либо блок.

Случай 1

Процедура Старт
           Если НадоПередатьДанные
                       // оператор ИСП действует до конца окружающего его блока
                       // в данном случае до конца блока Если
                       Исп Линия = Новый ЛинияПередачиДанных
                       Линия.ПередатьДанные()
                       //….  остальной код метода
                       //….
                       // вот тут, в конце блока ЕСЛИ будет освобождена переменная Линия
                       // тут закончится блок оператора ИСП
           КонецЕсли
КонецПроцедуры

Случай 2

Процедура Старт
           // оператор ИСП действует до конца метода
           // т.к. он не вложен ни в один блок
           Исп Линия = Новый ЛинияПередачиДанных
           Если НадоПередатьДанные
                       //вызов методов объекта может быть вложенным в другие блоки
                      Линия.ПередатьДанные()
           КонецЕсли
           //….  остальной код метода
           //….
           // вот тут, в конце метода будет освобождена переменная Линия
           // тут закончится блок оператора ИСП
КонецПроцедуры

На заметку: ВАЖНО! Переменная, объявленная в операторе Исп действительна до конца метода, однако, в конце блока Исп для неё будет вызван Завершитель и она получит значение Неопределено!!! Это не помешает Вам инициализировать и использовать её снова ниже по коду метода.

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

Сергей Рогаткин 27.06.2021 13:12

См. также

Ссылки