Какова причина не создания экземпляра объекта во время объявления? - PullRequest
16 голосов
/ 14 ноября 2011

Мне недавно пришлось вникать в некоторый код VB6, и я повсюду видел этот шаблон:

dim o as obj
set o = new obj

Почему бы не это?

dim o as new obj

Я помню, как 15 лет назадчто для этого была веская причина, но я не могу вспомнить, что это было сейчас.Кто-нибудь помнит?Причина все еще действительна?

Ответы [ 4 ]

22 голосов
/ 14 ноября 2011

Могут быть и другие причины, но в VB6 использование ключевого слова New при уменьшении яркости объекта может привести к неожиданным результатам, поскольку VB будет создавать экземпляр объекта всякий раз, когда на него ссылаются.

Dim objMyObject as New SomeObject

Set objMyObject = Nothing   ' the object is nothing

If objMyObject Is Nothing Then  ' referencing the object instantiates again
   MsgBox "My object is destroyed"  ' what you would probably expect
Else
   MsgBox "My object still exists"
End If
7 голосов
/ 14 ноября 2011

Этот вопрос затрагивает одну из многих причин, по которой опытным программистам не нравится VB6. Ключевое слово New изменяет способ работы объявленной переменной. Например:

Dim MyObject As MyClass
Set MyObject = New MyClass
Set MyObject = Nothing
Call MyObject.MyMethod()

... выдает исключение времени выполнения, в то время как это:

Dim MyObject As New MyClass
Set MyObject = Nothing
Call MyObject.MyMethod()

... нет. Лично, если я попытаюсь установить переменную в Nothing, то ссылка на нее снова - это почти наверняка ошибка, и я бы очень хотел, чтобы программа вылетала, большое спасибо. Это особенно важно в случае, когда класс распределяет ресурсы в инициализаторе (конструкторе) и должен избавиться от ресурсов в деструкторе. Довольно просто написать код, который неправильно ссылается на переменную, установленную на Nothing, возможно, когда вы хотите проверить значение результата или что-то еще. Это может привести к повторному созданию класса, в результате чего будут удалены все ненужные ресурсы.

Причина этого странного поведения заключается в том, что формы VB6 (которые являются классами) работают так, как их ожидает новичок. Существует неявно объявленная глобальная переменная с тем же именем и типом, что и у каждой определенной формы, поэтому:

Call frmMain.Show

... не падает. Это то же самое поведение. Это действительно делает:

If frmMain Is Nothing Then
    Set frmMain = New frmMain
End If
Call frmMain.Show

Это очень сильно противоречит тому, к чему мы привыкли в других объектно-ориентированных языках, поэтому, на мой взгляд, это плохая идея. Он пытается скрыть тот факт, что MyObject является ссылочным типом, и все же, когда вы пишете что-то вроде этого (без использования Set):

MyObject = New MyClass

... тогда вы получите исключение runtime вместо ошибки компилятора, потому что вы не использовали команду Set. Компилятор знает, это ссылочный тип ... почему я должен использовать Set, и даже если я это сделаю, почему бы не рассказать мне об этом раньше?

В любом случае, чтобы ответить на ваш вопрос, вам редко требуется поведение, подразумеваемое использованием синтаксиса Dim ... New, поскольку вы хотите контролировать построение и уничтожение объектов. Фактически, единственный раз, когда это имеет смысл, - это создание глобальных одноэлементных объектов (таких как frmMain выше), где вы просто хотите получить синтаксический сахар. Я бы сказал, что глобальные синглеты - плохая идея, так что если бы я мог отключить возможность использования синтаксиса Dim ... New, я бы сделал это.

6 голосов
/ 15 ноября 2011

Вот еще одна оговорка:

For x = 1 to 100
   dim obj as new MyObject

   'Do something with obj
Next

Можно ожидать, что новый объект создается 100 раз, но вы обнаружите, что он создается только в первый раз. Этот давно застал меня врасплох.

Я все еще использую эту запись все же. Просто убедитесь, что вы знаете поведение.

2 голосов
/ 04 сентября 2012

Я хотел бы добавить к ответу Брэндона Мура ...

Продолжая цикл ...

For x = 1 to 100
  Dim obj as New Collection
  obj.Add "New String Number " & x
Next x

Несмотря на то, что вы добавили 20 объектов в obj, когда x= 1, когда x = 2, все эти 20 предметов все еще будут там!тогда как, если бы вы установили obj = new myObject, то это не так!Это самая важная причина, так как однажды я оказался в этой большой области зацикливания в моем коде, в программу добавлялись разные элементы, и я понятия не имел, почему, ничего не удалялось и не сбрасывалось.

Итак, если бы вместо:

  Dim obj as New Collection

Вы написали следующее:

  Dim obj as Collection
  Set obj = New Collection

Тогда вы будете сбрасывать коллекцию obj каждый раз, что, вероятно, то, что вы хотите,но если вы хотите, чтобы он устанавливался только один раз, используйте метод As New Collection.Но, если вы захотите установить его один раз, вы, вероятно, поместите его вне цикла.

Кроме того, если вы не работаете в цикле, но переменная (Collection) определена в статической функцииили определяется с помощью ключевого слова static, применяется то же самое, не запускать Set obj = New Collection гарантирует, что у вас будут устаревшие данные от вашего последнего использования obj / Collection, что может быть очень плохо.

Итак, в заключение, два метода на самом деле очень разные (и могут иметь разное поведение)!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...