vba Dim As New vs Dim / Set 有什么区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42656468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between Dim As New vs Dim / Set
提问by Combinatix
In VBA, I can create objects one of two ways:
在 VBA 中,我可以通过以下两种方式之一创建对象:
'First way
Dim myCol1 As New Collection
'Second way
Dim myCol2 As Collection
Set myCol2 = New Collection
myCol1.Add "AAA" 'Works
myCol2.Add "BBB" 'Works as well
Is the second way just a more verbose version of the first way, or is there actually a difference between the myCol1 and myCol2 objects?
第二种方式只是第一种方式的更详细版本,还是 myCol1 和 myCol2 对象之间实际上存在差异?
回答by ThunderFrame
There are several key differences. You should definitely prefer the second Dim/Set
approach.
有几个关键区别。您绝对应该更喜欢第二种Dim/Set
方法。
Reason 1- With As New
, the object doesn't get created until a property or method of that object is called, but look at this example where setting the object to Nothing, and then calling a property/method causes the object re-instantiate itself:
原因 1- 使用As New
,在调用该对象的属性或方法之前不会创建对象,但请查看此示例,其中将对象设置为 Nothing,然后调用属性/方法会导致对象重新实例化自身:
Sub ShortcutInstantiation()
Dim x As New Collection
x.Add "FOO", "BAR"
Set x = Nothing
'This line implicitly recreates a new Collection
Debug.Print x.Count
Debug.Print x Is Nothing 'Prints False
End Sub
Sub SafeInstantiation()
Dim x As Collection
Set x = New Collection
x.Add "FOO", "BAR"
Set x = Nothing
'Throws error because x is nothing
Debug.Print x.Count
End Sub
Reason 2The As New
approach is slower, because VBA needs to check if it has instantiated the object before every singleproperty or method call.
原因 2该As New
方法较慢,因为 VBA 需要在每个属性或方法调用之前检查它是否已实例化对象。
Look at this pseudo code to see what VBA is doing behind the scenes:
看看这个伪代码,看看 VBA 在幕后做了什么:
Sub NotSoShortcutInstantiation()
Dim x As New Collection
If x Is Nothing Then Set x = New Collection
x.Add "FOO", "BAR"
If x Is Nothing Then Set x = New Collection
x.Add "FIZZ", "BUZZ"
If x Is Nothing Then Set x = New Collection
x.Add "CAR", "DOOR"
If x Is Nothing Then Set x = New Collection
Debug.Print x.Count
End Sub
Reason 3There can be critical timing differences if you object constructor does something afteryou expect it to, rather than when you explicitly instantiate it:
原因 3如果对象构造函数在预期之后执行某些操作,而不是在显式实例化它时执行某些操作,则可能存在严重的时序差异:
Compare the results of this code:
比较这段代码的结果:
Sub InstantiationTiming()
Dim foo As String
Dim x As New Class1
Debug.Print Format(Now(), "hh:mm:ss") & " x should be ready"
foo = x.foo
Dim y As Class1
Set y = New Class1
Debug.Print Format(Now(), "hh:mm:ss") & " y should be ready"
foo = y.foo
End Sub
The As New
approach prints:
该As New
方法打印:
06:36:57 x should be ready
06:36:57 Class Initialized
The Set y = New
approach prints:
该Set y = New
方法打印:
06:36:57 Class Initialized
06:36:57 y should be ready
回答by S Meaden
The As New
construct has legitimate uses. In a class, with a module level variable when you do not know which method will be called first then it saves some lines of code. So some code snippet I have lying around in a class is given here
该As New
构造具有合法用途。在一个类中,当您不知道首先调用哪个方法时,使用模块级变量可以节省一些代码行。所以这里给出了我在课堂上闲逛的一些代码片段
Option Explicit
Private mdicQueryStringParams As New Scripting.Dictionary
Function SafeItem(ByVal sKey As String, ByRef pvItem As Variant) As Boolean
If mdicQueryStringParams.Exists(sKey) Then
pvItem = mdicQueryStringParams.Item(sKey)
SafeItem = True
End If
End Function
Imagine very many more methods that rely upon an initialised mdicQueryStringParams
. You'd have to write guard code to ensure that it was created in all of these methods.
想象一下更多依赖于初始化的方法mdicQueryStringParams
。您必须编写保护代码以确保它是在所有这些方法中创建的。
Now at this point you're saying but you can use Sub Class_Initialize
to New
up upon class creation. Like this
现在,您说的是,但您可以使用Sub Class_Initialize
来New
创建类。像这样
Private Sub Class_Initialize()
Set mdicQueryStringParams = New Scripting.Dictionary
End Sub
But suppose I want to recycle/reset part of the class's state then I could write a Clear method which sets mdicQueryStringParams
to Nothing
. In this case Sub Class_Initialise
won't run again. Here on SO Mat's Mughas taught me that Static classes are possible in VBA (thanks!) so sometimes Sub Class_Initialise
will only run once.
但是假设我想回收/重置类的部分状态,那么我可以编写一个设置mdicQueryStringParams
为Nothing
. 在这种情况下Sub Class_Initialise
不会再次运行。SO Mat 的 Mug告诉我,在 VBA 中可以使用静态类(谢谢!)所以有时Sub Class_Initialise
只会运行一次。
(^ Admittedly I could set it to a New instance in the Clear method, yes, yes, I know, I know)
(^ 诚然,我可以在 Clear 方法中将其设置为 New 实例,是的,是的,我知道,我知道)
The point is with the As New
syntax you get a resurrectingvariable as well as auto-initialisation. Surely as developers this is another technique/pattern in our toolbox that we should exploit and not ban.
关键是使用As New
语法你会得到一个复活变量以及自动初始化。当然,作为开发人员,这是我们工具箱中的另一种技术/模式,我们应该利用而不是禁止。
In truth, I use it infrequently but I just don't like banningstuff.
事实上,我很少使用它,但我只是不喜欢禁止某些东西。