我最近不得不深入研究一些VB6代码,我看到了这个模式:
dim o as obj
set o = new obj
Run Code Online (Sandbox Code Playgroud)
为什么不呢?
dim o as new obj
Run Code Online (Sandbox Code Playgroud)
我记得15年前有一个很好的理由,但我不记得它现在是什么.谁还记得吗?原因仍然有效吗?
jac*_*jac 24
可能还有其他原因,但在VB6中使用New关键字时,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
Run Code Online (Sandbox Code Playgroud)
这个问题触及了经验丰富的程序员真正不喜欢VB6的众多原因之一.该New关键字改变声明的变量的工作方式.例如:
Dim MyObject As MyClass
Set MyObject = New MyClass
Set MyObject = Nothing
Call MyObject.MyMethod()
Run Code Online (Sandbox Code Playgroud)
...抛出运行时异常,而这:
Dim MyObject As New MyClass
Set MyObject = Nothing
Call MyObject.MyMethod()
Run Code Online (Sandbox Code Playgroud)
... 才不是.就个人而言,如果我去设置一个变量Nothing,那么再次引用它几乎肯定是一个错误,我真的很喜欢程序崩溃,非常感谢你.在类在初始化程序(构造函数)中分配资源并且需要去除析构函数中的资源的情况下,这一点尤为重要.编写错误引用变量集的代码是相当容易的Nothing,可能是在您想要检查结果值或其他内容时.这样做可能会导致类再次实例化,抓取所有不必要的资源.
这种奇怪的行为的原因是VB6的表单(它们是类)以新手期望它们工作的方式工作.有一个隐式声明的全局变量,其名称和类型与每个定义的表单相同,因此:
Call frmMain.Show
Run Code Online (Sandbox Code Playgroud)
......不会崩溃 这是相同的行为.它真的在做:
If frmMain Is Nothing Then
Set frmMain = New frmMain
End If
Call frmMain.Show
Run Code Online (Sandbox Code Playgroud)
这非常违背我们在其他面向对象语言中习惯的东西,因此,在我看来这是一个坏主意.它试图隐藏MyObject作为引用类型的事实,然而,当你写这样的东西时(不使用Set):
MyObject = New MyClass
Run Code Online (Sandbox Code Playgroud)
...然后您得到运行时异常而不是编译器错误,因为您没有使用该Set命令.编译器知道它是一个引用类型...为什么我必须使用Set,即使我这样做,为什么不早点告诉我它?
无论如何,要回答您的问题,您很少想要使用Dim ... New语法隐含的行为,因为您想要控制对象的构造和销毁.事实上,它唯一有意义的是构建全局单例对象(frmMain如上所述),你只需要语法糖.我认为无论如何全球单身人士都是个坏主意,所以如果我能够关闭使用Dim ... New语法的能力,我会的.
这是另一个警告:
For x = 1 to 100
dim obj as new MyObject
'Do something with obj
Next
Run Code Online (Sandbox Code Playgroud)
您可能希望新对象实例化100次,但您会发现它只是第一次实例化.很久以前这个让我措手不及.
我仍然一直使用这种表示法.只要确保你知道这种行为.