With
Заявления / Блоки
Однако, насколько я понимаю, конструкция With New ... будет иметь объект, помеченный как готовый к сборке мусора, когда он выходит за пределы области видимости.
Это и правда, и неправда. Это правда в том смысле, что все объекты помечены (пуристы могут придраться к этой терминологии, но детали не имеют отношения) как готовые к сборке мусора, когда они выходят за пределы области видимости. Но в этом смысле это также не совсем верно, поскольку в ключевом слове With
нет ничего особенного в отношении такого поведения. Когда объект выходит за пределы области видимости, он подлежит сборке мусора. Период. Это верно для области на уровне метода и верно для области на уровне блока (например, With
, For
, Using
и т. Д.).
Но вы используете With
не поэтому. Причина в том, что он позволяет вам последовательно устанавливать несколько свойств для глубоко вложенного объекта. Другими словами, предположим, что у вас есть объект, для которого вы хотите установить набор свойств, и вы получаете к нему доступ следующим образом: MyClass.MemberClass.AnotherMemberClass.Items(0)
. Видите все эти точки? (Теоретически) может стать неэффективным писать код, который должен снова и снова проходить через эту серию точек для доступа к одному и тому же объекту каждый раз, когда вы устанавливаете для него свойство. Если вы знаете что-нибудь о C или C ++ (или любом другом языке, в котором есть указатели), вы можете думать о каждой из этих точек как о разыменовании указателя. Оператор 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
не выйдет за ее пределы (и, следовательно, будет иметь право на сборку мусора), пока не закончится область более высокого уровня, но это вряд ли когда-либо будет актуальной проблемой. Прирост производительности (если таковой имеется) связан с обоими последними двумя фрагментами кода.
Настоящим преимуществом использования With
блоков в настоящее время является не производительность, а удобочитаемость. Дополнительные мысли о With
, возможных улучшениях производительности, стилистических предложениях и т. Д. См. В ответы на этот вопрос.
With New
?
Добавление ключевого слова New
к оператору With
имеет точно такой же эффект, который мы только что обсуждали (создание локальной временной переменной для хранения объекта), за исключением того, что это почти совершенно бессмысленно. Если вам нужно создать объект с New
, вы также можете объявить переменную для его хранения. Возможно, вам понадобится что-то сделать с этим объектом позже, например передать его другому методу, а вы не можете сделать это в блоке With
.
Кажется, что единственная цель With New
состоит в том, что он позволяет избежать явного объявления переменной, вместо этого заставляя компилятор делать это неявно. Назовите меня сумасшедшим, но я не вижу в этом никакой пользы.
Фактически, я могу сказать, что честно говоря, я никогда не видел никакого реального кода, который использует этот синтаксис. Единственное, что я могу найти в Google, - это подобная чушь (и В любом случае Call
- гораздо лучшая альтернатива).
Using
Заявления / Блоки
В отличие от With
, Using
невероятно полезен и должен часто появляться в типичном коде VB.NET. Однако его применимость очень ограничена: он работает только с объектами, тип которых реализует _ 27_ шаблон интерфейса. Вы можете убедиться в этом, проверив, есть ли у объекта метод Dispose
, который вы должны вызывать каждый раз, когда вы закончите с ним, чтобы освободить какие-либо неуправляемые ресурсы.
Это, кстати, правило, которому вы всегда должны следовать, когда у объекта есть Dispose
метод: вы должны всегда вызывать его всякий раз, когда вы заканчиваете использование объекта. Если вы этого не сделаете, это не обязательно конец света - сборщик мусора может спасти ваш бекон, - но это часть задокументированного контракта и всегда хорошая практика с вашей стороны вызывать Dispose
для каждого объекта, который его предоставляет.
Если вы попытаетесь обернуть создание объекта, который не реализует IDisposable
в блоке Using
, компилятор лает на вас и выдаст ошибку. Это не имеет смысла для других типов, потому что его функция по существу эквивалентна блоку _33 _ / _ 34_:
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
. Вам обязательно стоит вернуться и перепроверить свой код, чтобы убедиться, что вы используете его там, где это необходимо!
person
Cody Gray
schedule
21.03.2013
Using
лучше, чемWith New ...
, - это когда работаешь с неуправляемым объектом. Если кто-то не может предоставить мне хороший пример того, почему бы не использоватьWith New ...
для локального одноразового объекта, я не понимаю, почему я не должен использовать его, чтобы мой код оставался незагроможденным. - person yu_ominae   schedule 21.03.2013