С ... конец с vs Using in VB.NET
Я только что узнал, что как C#, VB.NET также имеет using
ключевое слово.
до сих пор я думал, что у него этого нет (глупо с моей стороны, я знаю...) и делал такие вещи вместо этого:
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
каковы последствия этого по сравнению с тем, чтобы сделать это с using
показания
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
обновление:
я должен добавить, что я знаком с тем, что using
оператор делает в том, что он располагает объектом когда конструкция выходит.
однако, насколько я понимаю With New ...
построить объект пометить объект как готовый для сборки мусора, когда он выходит из области видимости.
так что мой вопрос действительно есть, есть только разница в том, что с using
я сразу же отпущу память, тогда как с With
построить он будет выпущен всякий раз, когда GC чувствует, как это? Или я упускаю что-то большее?
есть ли какие-либо лучшие практические последствия? Должен ли я пойти и переписать весь код с помощьюWith New MyDisposableObject() ... End With
as Using o as New MyDisposableObject()
?
4 ответов
С помощью With...В конце можно выполнить ряд операторов для указанного объекта без указания имени объекта несколько раз.
блок Using ведет себя как попытка...Наконец, конструкция, в которой блок Try использует ресурсы, а блок Finally избавляется от них.
управляемые ресурсы удаляются сборщиком мусора без дополнительного кодирования с вашей стороны. Вам не нужно используя или С заявления. Иногда код требует неуправляемых ресурсов. Вы несете ответственность за их утилизацию. А используя блок гарантий, что Dispose метод на объекте вызывается, когда ваш код закончен с ними.
With
Заявления/Блоки
однако, насколько я понимаю, с новым ... построить объект пометить объект как готовый для сборки мусора, когда он выходит из области видимости.
это и правда, и неправда. Это правда в том смысле, что все объекты "помечены" (пуристы могут придираться к этой терминологии, но детали не актуальны) как готовые к сбору мусора, когда они выходят за рамки. Но тогда в этом смысле, это тоже не совсем верно, так как нет ничего особенного в With
ключевое слово в отношении этого поведения. Когда объект выходит за пределы области, он имеет право на сборку мусора. Период. Это верно для области уровня метода, и это верно для области уровня блока (например,With
, For
, Using
, etc.).
но это не то, почему вы используете With
. Причина в том, что он позволяет установить несколько свойств в последовательности на глубоко вложенный объект. В других слова, предположим, у вас есть объект, на котором вы хотите установить кучу свойств, и вы получаете к нему доступ таким образом:MyClass.MemberClass.AnotherMemberClass.Items(0)
. Видишь все эти точки? Это может (теоретически) стать неэффективным писать код, который должен работать через эту серию точек снова и снова, чтобы получить доступ к одному и тому же объекту каждый раз, когда вы устанавливаете на нем свойство. Если вы знаете что-нибудь о C или C++ (или любом другом языке, который имеет указатели), вы можете думать о каждой из этих точек как подразумевающей разыменование указателя. The With
заявление в основном проходит через все это косвенное только один раз,сохранение результирующего объекта во временной переменной, и позволяет устанавливать свойства непосредственно на этом объекте, хранящемся во временной переменной.
возможно, какой-то код поможет прояснить ситуацию. Всякий раз, когда вы видите точку, думаю может быть медленным!
предположим, что вы начинаете со следующего кода, извлекая объект 1 из глубоко вложенного Items
сбор и установка несколько свойств на нем. Посмотрите, сколько раз мы должны получить объект, даже если это точно тот же самый объект каждый раз?
MyClass.MemberClass.AnotherMemberClass.Items(0).Color = Blue
MyClass.MemberClass.AnotherMemberClass.Items(0).Width = 10
MyClass.MemberClass.AnotherMemberClass.Items(0).Height = 5
MyClass.MemberClass.AnotherMemberClass.Items(0).Shape = Circle
MyClass.MemberClass.AnotherMemberClass.Items(0).Texture = Shiny
MyClass.MemberClass.AnotherMemberClass.Items(0).Volume = Loud
теперь мы изменим этот код, чтобы использовать With
блок:
With MyClass.MemberClass.AnotherMemberClass.Items(0)
.Color = Blue
.Width = 10
.Height = 5
.Shape = Circle
.Texture = Shiny
.Volume = Loud
End With
эффект здесь, однако, идентичен следующим кодом:
Dim tempObj As MyObject = MyClass.MemberClass.AnotherMemberClass.Items(0)
tempObj.Color = Blue
tempObj.Width = 10
tempObj.Height = 5
tempObj.Shape = Circle
tempObj.Texture = Shiny
tempObj.Volume = Loud
конечно, вы не вводите новую область, так что tempObj
не выйдет из области (и, следовательно, будет иметь право на сборку мусора), пока не закончится область более высокого уровня, но это вряд ли актуальна. Прирост производительности (если есть) присоединяется к обоим последним двум фрагментам кода.
на реальные win использования With
блоки в настоящее время не производительность, а читаемость. Для больше мыслей на With
, возможно улучшение производительности, стилистические предложения, и так далее, см. ответы на этот вопрос.
With New
?
добавлять New
сайта на With
заявление точно такой же эффект, который мы только что обсуждали (создание локальной временной переменной для хранения объекта), за исключением того, что это почти совершенно бессмысленно. Если вам нужно создать объект с New
, вы также можете объявить переменную для ее хранения. Вам, вероятно, понадобится do что-то с этим объектом позже, например, передать его другому методу, и вы не можете сделать это в With
блок.
кажется, что единственная цель With New
это позволяет вы должны избегать явного объявления переменной, вместо этого заставляя компилятор делать это неявно. Можете считать меня сумасшедшим, но я не вижу в этом никакой пользы.
на самом деле, я могу сказать, что я честно никогда не видел никакого фактического кода, который использует этот синтаксис. Единственное, что я могу найти в Гугле бред такой (и Call
в любом случае, это гораздо лучшая альтернатива).
Using
Заявления/Блоки
в отличие от With
, Using
is невероятно полезно и должно часто появляться в типичном VB.NET код. Однако он очень ограничен в своей применимости: он работает только с объектами, тип которых реализует IDisposable
шаблон интерфейса. Вы можете сказать это, проверив, имеет ли объект Dispose
метод, который вы должны позвонить, когда вы закончите с ним, чтобы освободить неуправляемые ресурсы.
это, кстати, правило вы всегда должно следовать, когда объект имеет Dispose
способ: вы должны всегда вызовите его, когда вы закончите использовать объект. Если вы этого не сделаете, это не обязательно конец света-сборщик мусора может спасти ваш бекон, но это часть документированного контракта и всегда хорошая практика с вашей стороны, чтобы позвонить Dispose
для каждого объекта, который его предоставляет.
если вы пытаетесь обернуть создание объекта, который не реализовать IDisposable
в a Using
block, компилятор будет лаять на вас и генерировать ошибку. Это не имеет смысла для любых других типов, потому что его функция по существу эквивалентна Try
/Finally
блок:
Try
' [1: Create/acquire the object]
Dim g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ... etc.
End Try
Finally
' [3: Ensure that the object gets disposed, no matter what!]
g.Dispose()
End Finally
но это уродливо и становится довольно громоздким, когда вы начинаете гнездиться (например, если бы мы создали Pen
объект, который также необходимо удалить). Вместо этого мы используем Using
, который имеет тот же эффект:
' [1: Create/acquire the object]
Using g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ...etc.
End Using ' [3: Ensure that the object gets disposed, no matter what!]
на Using
оператор работает как с объектами, которые вы сначала приобретаем (используя New
ключевое слово или путем вызова метода, как CreateGraphics
), и с объектами, которые вы уже создали. В обоих случаях это гарантирует, что Dispose
метод вызывается, даже если исключение выбрасывается где-то внутри блока, что гарантирует правильное размещение неуправляемых ресурсов объекта.
меня немного пугает, что вы написали код в VB.NET без зная о Using
заявление. Вы не используете его для создания всех объектов, но это очень важно, когда вы имеете дело с объектами, которые реализуют IDisposable
. Вы определенно должны вернуться и перепроверить свой код, чтобы убедиться, что вы используете его там, где это необходимо!
разница Using With...End End
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
звонки cn.Dispose()
автоматически при выходе из области видимости (End Using
). Но в With New...End
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
.Dispose () явно не вызывается.
также с именованным объектом вы можете создавать часы и ?cn
в окне immediate. С безымянным объектом вы не можете.
используя подключение... Конец использования: будьте осторожны !!! Эта инструкция закроет вашу базу данных подключение !
в середине модуля или формы(форм) i.e.добавление или обновление записей, это закроет соединение. При попытке выполнить другую операцию в этом модуле вы получите ошибку базы данных. Для связи, я больше не использую его. Вы можете использовать Try... End Try wihthouth оператор Using.
Я открываю соединение при вход в модуль и закройте его при выходе. Это решает проблему.