簡體   English   中英

Dim As New與Dim / Set之間有什么區別

[英]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_InitializeNew基於類的創建起來。 像這樣

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM