5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

オブジェクト型配列→Variant型の罠

Last updated at Posted at 2017-01-22

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

DynamicObjectArray.png

まとめ

Variant型は便利だが、具象オブジェクト型配列を入れる場合注意が必要。
汎用性を落として良い場面では、引数の型・戻り値の型を対象オブジェクト型の配列として宣言すること。
Genericコレクションが欲しい。

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?