Цель оператора «using» состоит в том, чтобы обеспечить выполнение некоторого типа операции очистки при выходе из блока кода, независимо от того, происходит ли этот выход из-за сбоя, исключения или return
.Когда блок выходит из любого из этих средств, он вызовет Dispose
с параметром using
.Блок существует, в некотором смысле, в пользу того, что указывается в качестве параметра using
, и, в общем, этой вещи не будет волновать, почему был завершен блок.
Есть несколько необычныхслучаи, для которых положения могут быть полезны;уровень их дополнительной полезности был бы намного ниже, чем при наличии using
на первом месте (хотя, возможно, и лучше, чем некоторые другие функции, которые реализаторы считают нужным предоставить):
(1) Существует очень распространеннаяшаблон в конструкторах или фабриках объектов, которые инкапсулируют другие IDisposable
объекты;если конструктор или фабрика выходят через исключение, инкапсулированные объекты должны быть Dispose
d, но если они выходят через return
, они не должны.В настоящее время такое поведение должно быть реализовано с помощью try
/ catch
или путем объединения try
/ finally
с флагом, но было бы ИМХО полезно, если бы существовал вариант using
, который бы вызывал толькоDispose
при выходе через исключение или оператор keep using
, который обнуляет временное значение, используемое оператором using
для хранения объекта, который нуждается в удалении (поскольку using
не может предшествовать идентификатор, такой какфункция может быть добавлена способом, аналогичным yield return
).
(2) В некоторых случаях было бы полезно, если бы ключевое слово finally
расширялось, чтобы принимать аргумент Exception
;он будет содержать исключение, из-за которого защищенное предложение будет завершено (если оно есть), или null
, если защищенное предложение будет завершено нормально (через возврат или откат), и если блок using
может использовать interface IDisposeExOnly {void DisposeEx(Exception ex);}
и Interface IDisposeEx : IDisposable, IDisposableExOnly {}
(во время компиляции выбрано DisposeEx()
, если реализовано, или Dispose()
в противном случае).Это может позволить объектам на основе транзакций безопасно поддерживать автоматическую фиксацию (т. Е. Выполнять фиксацию, если переданное исключение null
, или откат, если не ноль), а также позволит улучшить ведение журнала в ситуациях, когда Dispose
терпит неудачу как следствие проблемы в пределах защищенного предложения (правильнее было бы для Dispose
сгенерировать исключение, которое инкапсулирует как исключение, ожидающее его вызова, так и исключение, которое возникло как следствие, но естьв настоящее время нет чистого способа сделать это).
Я не знаю, будет ли когда-нибудь Microsoft добавлять такие функции;первая и первая часть второй будут обрабатываться полностью на уровне языка.Последняя часть второго будет на уровне структуры.