API Basic Using - LIHACHTETAN/ClassicUO-BadNewbie-BasicIDE GitHub Wiki

Using / End Using

ClassicUO • Basic

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

Точный синтаксис

Dim resource = MemoryStream()
Using resource
    statements
End Using
Using resourceExpression
    statements
End Using

Параметры

  • resourceExpression — Вычисляется один раз при входе. Подходят объекты File(path), MemoryStream() и CreateTimer(...). Освобождение таймера окончательно останавливает его; см. Basic.Timers. Строка, число, List и Dictionary вызывают ошибку с номером строки до выполнения тела. Переменную объявляйте заранее: объявления в заголовке, As New, список через запятую и пользовательские методы Dispose не поддержаны.
  • statements / End Using — Тело использует сохранённый объект; End Using закрывает его. Переменная остаётся доступной, но ресурс уже закрыт. Для нескольких ресурсов вкладывайте блоки. Переприсваивание переменной не меняет исходный объект, который будет закрыт.

Возвращает

Оператор ничего не возвращает и не является логической проверкой. Return внутри тела сохраняет обычный смысл, но сначала освобождается ресурс. IsClosed в примерах — пользовательская функция с результатом 1/True или 0/False. Итоговые результаты Main — строки, а не признаки успеха.

Поведение

  • File(path) создаёт оболочку: внутри блока вызовите Create() для записи либо Open() для чтения. Освобождение вызывает Close(), сбрасывает буфер и закрывает дескриптор. MemoryStream() создаёт пустой поток; после освобождения Length() вызывает ошибку. Примеры работают в памяти и не создают файлов.
  • Компилятор создаёт защищённый блок с нативным освобождением. Интерпретатор один раз сохраняет объект в текущем вызове. End Using, Return, Exit, Continue и переход наружу закрывают ресурсы от внутреннего к внешнему. Переход внутрь тела запрещается до запуска.
  • При обычной ошибке ресурсы закрываются до внешнего Catch. Неудачный Dispose повторно не вызывается; внешние ресурсы тоже освобождаются. Аварийный стоп пропускает скриптовые Catch/Finally, но закрывает нативные ресурсы; ошибка закрытия не подменяет отмену. Пауза удерживает ресурс до продолжения либо стопа. Новые потоки не создаются; принудительно прервать зависшую операцию закрытия ОС этот оператор не может.
  • Чтобы обработать ошибку, сохранив ресурс открытым, поместите Try/Catch внутрь Using. Необработанная ошибка тела при On Error Resume Next закрывает ресурс и продолжает выполнение после всего блока Using. On Error GoTo не может ссылаться на метку внутри тела Using: это означало бы повторный вход в уже закрытую защищённую область.
  • После выхода из Using с ошибкой Resume во внешнем обработчике On Error GoTo повторяет весь блок с заголовка и заново вычисляет выражение ресурса. Resume Next продолжает сразу после End Using. Если переменная по-прежнему содержит закрытый объект, повторный вход не открывает его: для повторной попытки используйте выражение, создающее новый ресурс. Уже выполненные действия тела могут повториться.

Примеры

1. Закрыть поток памяти

# stream — ресурс; size получает Length()=0, пока поток открыт. После End Using функция IsClosed(stream) ловит ошибку закрытого потока и возвращает True=1. Main возвращает "0:1". ByVal копирует ссылку, а не содержимое потока. Учебный IsClosed считает любую ошибку Length признаком закрытия и предназначен для этих потоков.
Option Explicit On
Function IsClosed(ByVal stream) As Boolean
    Try
        Dim size = stream.Length()
        Return False
    Catch closed
        Return True
    End Try
End Function

Sub Main()
    Dim stream = MemoryStream()
    Dim size = -1
    Using stream
        size = stream.Length()
    End Using
    Return CStr(size) & ":" & CStr(IsClosed(stream))
End Sub

Разбор параметров и выполнения:

stream — ресурс; size получает Length()=0, пока поток открыт. После End Using функция IsClosed(stream) ловит ошибку закрытого потока и возвращает True=1. Main возвращает "0:1". ByVal копирует ссылку, а не содержимое потока. Учебный IsClosed считает любую ошибку Length признаком закрытия и предназначен для этих потоков.

2. Вернуться из вспомогательной функции

# ReadLength(stream) принимает ресурс под управление своего Using и вычисляет Integer 0. Return закрывает поток до передачи size в Main. Следующий Length вызывает ошибку; closed становится True, а Main возвращает "0:1". Не передавайте сюда ресурс, который вызывающему коду ещё нужен открытым.
Option Explicit On
Function ReadLength(ByVal stream) As Integer
    Using stream
        Return stream.Length()
    End Using
End Function

Sub Main()
    Dim stream = MemoryStream()
    Dim size = ReadLength(stream)
    Dim closed = False
    Try
        Dim after = stream.Length()
    Catch problem
        closed = True
    End Try
    Return CStr(size) & ":" & CStr(closed)
End Sub

Разбор параметров и выполнения:

ReadLength(stream) принимает ресурс под управление своего Using и вычисляет Integer 0. Return закрывает поток до передачи size в Main. Следующий Length вызывает ошибку; closed становится True, а Main возвращает "0:1". Не передавайте сюда ресурс, который вызывающему коду ещё нужен открытым.

3. Освободить вложенные ресурсы при ошибке

# outer и inner — отдельные потоки. Throw "demo" выводит из обоих блоков: сначала закрывается inner, затем outer. Catch сохраняет исходное сообщение. IsClosed возвращает по 1 для каждого, поэтому Main возвращает "demo:2". Число 2 — количество закрытых объектов, а не Boolean.
Option Explicit On
Function IsClosed(ByVal stream) As Boolean
    Try
        Dim size = stream.Length()
        Return False
    Catch closed
        Return True
    End Try
End Function

Sub Main()
    Dim outer = MemoryStream()
    Dim inner = MemoryStream()
    Dim message = ""
    Try
        Using outer
            Using inner
                Throw "demo"
            End Using
        End Using
    Catch problem
        message = problem
    End Try
    Return message & ":" & CStr(IsClosed(outer) + IsClosed(inner))
End Sub

Разбор параметров и выполнения:

outer и inner — отдельные потоки. Throw "demo" выводит из обоих блоков: сначала закрывается inner, затем outer. Catch сохраняет исходное сообщение. IsClosed возвращает по 1 для каждого, поэтому Main возвращает "demo:2". Число 2 — количество закрытых объектов, а не Boolean.


en · ru · uk · fr · de · it · es · zh-tw · ja · ko

Basic