VB には「クラスビルダユーティリティ」というツールがついていて、クラスを作る時の手間を減らすことができる。このツールでは通常のクラス以外にコレクションクラスも作れるのだが、これで作ったコレクションは、COM コレクショクラスの規約に従っていて、VB の For Each 文で要素を列挙することができる。
が、そもそも For Each 文に対応させるというのは、どういうことなのか。
for…each が利用できるコレクションには、DISPID_NEWENUM という dispid を持つ _NewEnum というメソッドがなければなりません。_NewEnum という名前の先頭にあるアンダースコアは、このメソッドをオブジェクト ブラウザからは隠すということを示します。
名前が示すように、_NewEnum が新しい列挙子オブジェクトを指す IEnumVARIANT ポインタを返すように書かなければなりません。配列に複数の添え字を持てるように、コレクションも複数の列挙子を持てます。
Dr.GUI と COM オートメーション、第 3 部:続 COM のすばらしきデータ型
これを VB でやるには、まず、コレクションクラスに NewEnum という読み取り専用プロパティを作成する。このプロパティの型は IUnknown。で、[ツール]→[プロシージャ属性] の [詳細] で、以下の 2 つを行う。
- プロシージャ ID を -4 (= DISPID_NEWENUM) に設定する。
- [このメンバを非表示にする] にチェックを入れる (= NewEnum→_NewEnum)。
後は、NewEnum プロパティが IEnumVARIANT を返せばいいのだが……上記のクラスビルダユーティリティの場合は、内部で要素管理に使っているコレクションのものをそのまま返している。VB では実装できないのかな?