#vb6
#vb6
Вопрос:
Недавно мне пришлось покопаться в коде VB6, и я повсюду видел этот шаблон:
dim o as obj
set o = new obj
Почему бы и нет?
dim o as new obj
Я помню, что 15 лет назад для этого была веская причина, но я не могу вспомнить, какая это была сейчас. Кто-нибудь помнит? Действительна ли причина по-прежнему?
Комментарии:
1. Хм, интересно, я кодировал на VB6 в течение 3 лет, и что я помню, так это то, что эти два варианта совершенно верны.
2.
dim o as new obj
создается при первом доступе, не раньше. Таким образом, каждый вызов свойства / метода для него сопряжен с накладными расходами на проверку переменной наNothing
.3. @wqw Каждое свойство имеет накладные расходы на проверку отсутствия ничего даже после создания экземпляра объекта или только в первый раз?
4. @AngryHacker Да, потому что вы вообще не можете получить доступ к свойствам объекта, если только объект не является «Not Nothing». Таким образом, каждый доступ подразумевает «Если obj ничего не значит, тогда установите obj = New myObj» перед ним.
5. @wqw давайте не будем забывать, что после использования в цикле метод «New obj» не уничтожит и не воссоздаст объект заново, однако, если вы делаете «Dim o как obj» и «Set o = New obj», то каждый раз, когда выполняется эта последовательность, она уничтожает и воссоздает переменную «o». Особенно, если объект является типом коллекции, и он не уничтожается и не создается заново (как это было бы при выполнении только «Dim o как новая коллекция»), каждый раз, когда вы добавляете элементы в коллекцию («o» в данном случае, когда в цикле), он будет просто продолжать повторно добавлять элементы в коллекцию, и у вас будут устаревшие данные из предыдущего цикла, большая разница. Смотрите мой ответ.
Ответ №1:
Могут быть и другие причины, но в 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
Комментарии:
1. Именно по этой причине.
2. Этот ответ движется в правильном направлении, но, возможно, не лучшая формулировка? Я бы не использовал непредсказуемый . Результаты полностью предсказуемы , но часто неожиданны для большинства разработчиков. Результаты также могут означать, что ошибки программирования вызывают слегка неправильное поведение во время выполнения, а не приятное простое исключение «Переменная объекта не установлена»
3. @MarkJ Вы высказали отличную мысль, и я соответствующим образом отредактировал ответ
Ответ №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
синтаксиса, я бы это сделал.
Комментарии:
1. Из всех многих веских причин, по которым vb6 не нравится, я бы сказал, что эту едва ли стоит даже упоминать, ха-ха
2. @Mat’Smug достаточно справедлив в отношении IDE, но подобные атрибуты по существу невидимы для программистов VB6. На самом деле, они вообще где-нибудь документированы?
Ответ №3:
Вот еще одно предостережение:
For x = 1 to 100
dim obj as new MyObject
'Do something with obj
Next
Можно ожидать, что новый объект создается 100 раз, но вы обнаружите, что он создается только в самый первый раз. Это давно застало меня врасплох.
Хотя я все еще постоянно использую эту нотацию. Просто убедитесь, что вы знаете поведение.
Комментарии:
1. это тоже сбило меня с толку
2. Частично проблема здесь действительно заключается в неправильном использовании,
Dim
посколькуMyObject
область действия всегда будет на уровне процедуры, а не на уровне цикла. Поэтому размещение его внутри цикла for вводит в заблуждение.
Ответ №4:
Я хотел добавить к ответу Брэндона Мура…
Итак, продолжаем цикл…
For x = 1 to 100
Dim obj as New Collection
obj.Add "New String Number " amp; 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, что может быть очень плохо.
Итак, в заключение, два метода на самом деле очень разные (и могут иметь разное поведение)!