[英]What's the difference between Dim As New vs Dim / Set
在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
第二種方式是第一種方式的更詳細的版本,還是myCol1和myCol2對象之間實際上有區別?
有幾個關鍵的區別。 你絕對應該選擇第二種Dim/Set
方法。
原因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
原因2 As New
方法較慢,因為VBA需要檢查它是否在每個屬性或方法調用之前實例化了對象。
看看這個偽代碼,看看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
原因3如果對象構造函數在您期望之后執行某些操作,而不是在您顯式實例化它時,可能存在嚴重的時序差異:
比較此代碼的結果:
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
As New
方法打印:
06:36:57 x should be ready
06:36:57 Class Initialized
Set y = New
方法打印:
06:36:57 Class Initialized
06:36:57 y should be ready
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
想象一下,有很多方法依賴於初始化的mdicQueryStringParams
。 您必須編寫保護代碼以確保它是在所有這些方法中創建的。
現在,在這一點上你說,但你可以使用Sub Class_Initialize
到New
基於類的創建起來。 像這樣
Private Sub Class_Initialize()
Set mdicQueryStringParams = New Scripting.Dictionary
End Sub
但是假設我想循環/重置類的狀態,那么我可以寫一個將mdicQueryStringParams
設置為Nothing
的Clear方法。 在這種情況下, Sub Class_Initialise
將不再運行。 在這里,SO Mat的Mug告訴我靜態類在VBA中是可能的(謝謝!)所以有時Sub Class_Initialise
只會運行一次。
(不可否認,我可以在Clear方法中將其設置為New實例,是的,是的,我知道,我知道)
關鍵在於使用As New
語法,您將獲得一個復活變量以及自動初始化 。 當然,作為開發人員,這是我們工具箱中的另一種技術/模式,我們應該利用而不是禁止。
事實上,我很少使用它,但我只是不喜歡禁止的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.