VBAではVariant型に配列を代入することができる。
このとき、値型配列では正しく型が伝播され、特に問題は起きない。
Sub 値型配列の場合、正しく型が伝播する()
Dim Lngs() As Long
ReDim Lngs(0 To 1)
Dim tmp As Variant
tmp = Lngs
Debug.Print VBA.TypeName(Lngs) 'Long()
Debug.Print VBA.TypeName(tmp) 'Long()
tmp(0) = 1
'tmp(1) = "a" ’エラー Long型にStringは入らないので
Lngs = tmp
Stop
End Sub
対して、具象オブジェクト型配列をVariant型に入れるとObject型配列として扱われ、具象型によるフィルターが効かなくなる(Variant型ではそこまでの情報を保持できないため)。
Sub 動的オブジェクト配列の罠()
Dim cols() As VBA.Collection
ReDim cols(0 To 1)
Set cols(0) = New VBA.Collection
'Set cols(1) = Err 'エラー 型が一致しません。→OK
Dim tmp As Variant
tmp = cols
Debug.Print VBA.TypeName(cols) 'Object()
Debug.Print VBA.TypeName(tmp) 'Object()
Set tmp(0) = New VBA.Collection
Set tmp(1) = VBA.Err
cols = tmp '←!?
Set cols(0) = cols(1) '←!?
'↑ErrObject
Stop
End Sub
まとめ
Variant型は便利だが、具象オブジェクト型配列を入れる場合注意が必要。
汎用性を落として良い場面では、引数の型・戻り値の型を対象オブジェクト型の配列として宣言すること。
Genericコレクションが欲しい。