В чем причина не создания экземпляра объекта во время объявления?
Мне недавно пришлось вникать в какой-то код VB6, и я видел этот шаблон повсюду:
dim o as obj
set o = new obj
Почему не это?
dim o as new obj
С 15 лет назад я помню, что для этого была веская причина, но я не могу вспомнить, что это было сейчас. Кто-нибудь помнит? Является ли причина действительной?
Ответы
Ответ 1
Могут быть другие причины, но в VB6, используя ключевое слово Новое, когда вы Dim, объект может вызвать неожиданные результаты, потому что 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
Ответ 2
Этот вопрос затрагивает одну из многих причин, по которым опытные программисты действительно не любят 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
... тогда вы получаете исключение во время выполнения вместо ошибки компилятора, потому что вы не использовали команду Set
. Компилятор знает, что это ссылочный тип... почему мне нужно использовать Set
, и даже если я это сделаю, почему бы не рассказать мне об этом раньше?
Во всяком случае, чтобы ответить на ваш вопрос, вы редко хотите, чтобы поведение подразумевалось с помощью синтаксиса Dim ... New
, потому что вы хотите контролировать строительство и уничтожение объектов. Фактически, единственный раз, когда это когда-либо имело бы смысл, заключается в построении глобальных одноэлементных объектов (например, frmMain
выше), где вам просто нужен синтаксический сахар. Я бы сказал, что глобальные синглтоны - это плохая идея, так что, если бы я мог отключить возможность использования синтаксиса Dim ... New
, я бы это сделал.
Ответ 3
Здесь еще одна оговорка:
For x = 1 to 100
dim obj as new MyObject
'Do something with obj
Next
Вы можете ожидать, что новый объект будет создан 100 раз, но вы обнаружите, что он создается только в первый раз. Этот человек давно поймал меня на страже.
Я все еще использую эту нотацию все время. Просто убедитесь, что вы знаете поведение.
Ответ 4
Я хотел добавить в ответ Брэндона Мура...
Итак, продолжая цикл...
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, то это не так! Это самая важная причина, так как я когда-то был пойман в этом в большой области цикла в моем коде, материал добавлялся по всей программе, и я понятия не имел, почему ничего не удалялось или reset.
Итак, если вместо:
Dim obj as New Collection
Вы написали foilowing:
Dim obj as Collection
Set obj = New Collection
Тогда у вас будет коллекция obj reset каждый раз, что, вероятно, вы хотите, но если вы хотите, чтобы она только установила один раз, используйте метод As New Collection. Но, если вы хотите установить его один раз, вы, вероятно, поместите его вне цикла.
Кроме того, если вы не работаете в цикле, но переменная (Collection) определяется в статической функции или определяется с помощью статического ключевого слова, применяется то же самое, но не выполняется Set obj = New Collection убедитесь, что у вас есть устаревшие данные из вашего последнего использования obj/Collection, что может быть очень плохо.
Итак, в заключение, два метода на самом деле очень разные (и могут иметь другое поведение)!