独自コレクションクラスをDictionaryで作る

おおそうか、引用のbqモジュールを使うとちゃんと内容を取り込んでくれるんですね。毎回動的に読み込みにいってるわけではないと。
しかし改行が消されてしまってちょっといけてないな。うーむ。結局整形済みテキスト用の>||<を使うことに…
元のURLは
http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list86.shtml

4.コレクションクラスが作成できない

まず、VBでコレクションクラスを作成する方法は、VBのヘルプに詳説がありますのでそちらを
参照してください。
コレクションの作成方法
http://www.microsoft.com/japan/developer/library/vbcon98/vbconcreatingyourowncollectionclasses.htm

一方VBSでは、
Private(/Public) hogehoges As New Collection
という記述ができないため、VBのように、Collectionオブジェクトを利用する
方法は使用できないわけです。

ただし、Collectionオブジェクトの代わりにDictionary(Scripting.Dictionary)オブジェクトを
併用して、コレクションクラスもどきを作成するというテクもあります。
こちらをご覧ください。
 aspZone.com - ASP File Upload using VBScript http://www.aspzone.com/articles/john/aspUpload/

ここで用いられているclsCollectionクラスは、Dictionaryオブジェクトを使うことで
擬似的なコレクションクラスを実現しています。
概念的には、先ほど示したVBヘルプにおける、「プライベート コレクションの例」に
近いものです。要するに、Class内で作成したDictionaryオブジェクトをPrivate変数に格納しておき、
外部からそこに値を格納したり、読み出したりする際はクラスのプロパティやメソッドを
通して行うわけです。

(Addメソッドに、値をvalidateするコードを加えるとさらにGoodですね。
というか、こういうコードを追加しないとわざわざClassにした意義が薄れるわけですが。
If IsObject(Value) And TypeName(Value)="clsNantoka" Then
 DictionaryにAddするコード
End If
のような感じで)

もちろん、clsCollectionクラスは本質的にはコレクションクラスではないので、
For Each...Nextで各値を取り出すことはできません。

ただ、Itemsメソッドを定義して、Dictionaryの各値が格納された1次元配列を返すように
しておけば、実用上はほぼ問題ないと思います。
clsCollectionに次のコードを追加してください。

Public Function Items()
Items=m_objDicItems.Items
End Function

これで、クライアント側からは
For Each obj In oCollection.Items
...
Next
のようにして各値が取り出せます。Itemsがカッコ悪いですが我慢しましょう。

(For Each...Nextができるようにするためには、コレクションオブジェクト(この例では
Dictionaryオブジェクトだが同じことだ)の列挙子のIUnknownインターフェイスを返す
NewEnumメソッドをクラスに実装した上で、NewEnumメソッドを非表示メンバにし、
プロシージャIDを-4に設定するとヘルプにはあるのだが、VBSのClassステートメントでは
不可能…だと思う。ただ、Dictionaryオブジェクトの_NewEnumメソッドは、
VBSでもobjDictionary.[_NewEnum]のようにすれば実行可能だし、TypeName関数で
調べたところちゃんとUnknownクラスのオブジェクトが返って来ているので、
後はクラスで実装するNewEnumメソッドのプロシージャIDを設定できれば、
完全なコレクションが作成可能なんではなかろうか?
もっとも、Classステートメントでは無理そうだが、もしかするとWSCなら可能なのかも
しれない。というのも、WSCではのように、
dispIDを指定することができるからだ。もっとも、DictionaryオブジェクトでFor Each...Next
した際に返って来るのはKeyのセットなので、clsCollectionのようにValueの方に
オブジェクトを入れるのではなく、Keyにオブジェクトを入れなきゃならないが(できるのか?)。
うん、何か大きな勘違いをしてなければ、できそうだぞ。これ、後で試してみよう)

(さらに余談ですが、JScriptでは、単独ではコレクションどころか、SafeArrayすら作れなかったり
します。そのため、SafeArrayを作成するためだけのCOMコンポーネントがあったりする。
詳しくはhttp://www.imasy.or.jp/~hir/hir/tech/js_tips.html#safearray 参照。
このページはJScriptのtipsが色々と書いてあって参考になります。

VBSの配列やCOMのコレクションにアクセスするのにも、わざわざVBArrayオブジェクトや
Enumeratorオブジェクトを用いる必要があって、そこはFor Each...Nextが使える
VBScriptの方が有利ですよね。もっともJScript.NETではfor...inが拡張されて
コレクションも列挙できるようになったんですが。一方でSafeArrayは.NETでは型としては
消滅したらしい?です)