Skip to content

Instantly share code, notes, and snippets.

@dck-jp
Created August 7, 2012 10:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dck-jp/3284359 to your computer and use it in GitHub Desktop.
Save dck-jp/3284359 to your computer and use it in GitHub Desktop.
a problem of "Dim As New" @ VBA
Public data As String
Option Explicit
' VBAでコンパイル時に、Dim(特にDim As New)文が、
' プロシージャ/メソッドの先頭に集められることによる弊害に関する検証
'[背景]
' Dim As New文は、
' 宣言と初期化が一度にできるので(他の言語とコーディングスタイルを合わせられるので)
' コードがすっきりするけど、
' VBAでは、実行時(コンパイル後)に、Dim文が各プロシージャ/メソッドの先頭に再配置される仕様のため、
' ループ内で使うと危ないよと@igetaさんから指摘を頂いたので色々メモ。
'[以下のコードの概要]
' ・他のプログラミング言語同様、変数のスコープが小さく見える(*)ようループ内で変数を初期化
' ・配列内には、異なるインスタンスを代入するのが目的。
' (*)上述のVBAの仕様により、実際にはスコープは小さくならない。
'[補足]
'※1 実行時(コンパイル後)には、Dim文は各プロシージャ/メソッドの先頭に位置するが、
' 構文チェック(*)は、Dim文より後ろで変数が使われているかで判断される。
' (*)コンパイル前に実行される
'
'※2 ループ内で構造体(Type)を初期化する場合、
' 構造体の配列への代入は、DeepCopyのため、希望する動作になる。
'
'※3 モジュール名を構造体と同じ名前にするとコンパイル時にエラーが出る(*)
' (*)コンパイラが、構造体とモジュールの区別をつけられないっぽい
'
'[私感]
' ・VBAでは、ループや条件分岐によって、変数のスコープが小さくなったりしないことを念頭に入れておくと安全?
' ・構造体を使うよりは、データクラスを使う方が、
' 例外規定を覚える手間が減る(コーディングルールをシンプルに保てる)ので良いかも?
'safety
' :(マルチステートメント)を使って、初期化と宣言を一行で。
Sub TestDimAndNew()
Dim class1s As New Collection
Dim i As Integer
For i = 0 To 2
Dim cls1: Set cls1 = New Class1
cls1.data = Str(i)
Call class1s.Add(cls1)
Next i
End Sub
'warning: all of items in class1s are same!
' Dim As New文を使って、初期化と宣言を一行で。
Sub TestDimAsNew()
Dim class1s As New Collection
Dim i As Integer
For i = 0 To 2
Dim cls1 As New Class1
cls1.data = Str(i)
Call class1s.Add(cls1)
Next i
End Sub
'safety
'構造体を用いて同じことをやる
'構造体はCollectionsに代入できないので、配列で。
Sub TestDimWithType()
Dim type1s(2) As TypeOne
Dim i As Integer
For i = 0 To 2
Dim tp1 As TypeOne
tp1.data = Str(i)
type1s(i) = tp1
Next i
End Sub
Type TypeOne
data As String
End Type
@dck-jp
Copy link
Author

dck-jp commented Jun 5, 2015

@igetaさんに、
「それちょっと嘘です。Dim As New は遅延初期化を行います。宣言した場所ではなく、メソッド呼び出しなどで、実際に最初に使われるときにインスタンス化されます」https://twitter.com/igeta/status/606611110465126400

という、ツッコミを頂いたので追補版を下記に作りました。
https://gist.github.com/dck-jp/24daacc002d6b5c03f33

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment