なぜCOM CollectionはC#で配列として扱えないのか

まずC#の配列としてCom Collectionが扱えない理由ですが、.NET Framework(Fx)のランタイムがCOM Collectionをマーシャリング(型変換)するときに、ArrayListクラスへの変換もしくはICollectionの実装をしないためです。この為、C#では配列としてCOM Collectionを扱うことが出来ません。
.NET FrameworkからCOMを使用するための相互運用メカニズムであるRCW(Runtime COM Wrapper)は、COM Collectionの_NewEnumメソッドを.NET FxのIEnumerableインターフェイスが持つGetEmumeratorメソッドに置き換えます。RCWがこのような機能を持つため、VSやTlbImplが作成するラッパクラスは、クライアントがEnumerator(列挙子)を使ってforeach文が使えるようにIEnumeratorインターフェイスを用意します。RCW、ラッパクラス作成ツールがこのような挙動をするので、C#ではCOM Collectionからforeach文でCOM Collectionの中身(多くの場合にはCOMのCoClass)を取り出すことが出来ます。逆に言えば、COM Interopのメカニズムがしてくれることはここまでなので、VSのインテリセンスはあたかもC#の配列としてCOM Collectionを扱えるような挙動をしますが、実際にはCOM InteropのメカニズムがC#の配列(ArrayList)に変換してくれるわけではないので、foreach文使うか、IEnumeratorインターフェイスの持つメソッドを使ってCollection内のオブジェクトを操作する(取り出す)必要があります。
当然のことながら、.NET Fx 2.0以降でサポートされているGenericsもサポートされていません。
配列として扱えないままではコード内のハンドリング悪いと判断される場合には、一度.NET Fxの適当なCollectionクラスか、GenericsのCollectionクラスにCOM Collectionの中身を移し替えてしまった方が良いでしょう。それも単純にメソッド一発という具合には行かないわけですが。まぁADOで分離レコードセットがサポートされるまでは、VBでも同じようなこと(Collectionの移し替え)を良くやったでしょう?
参考:
IEnumerable メンバ
http://msdn2.microsoft.com/ja-jp/library/system.collections.ienumerable_members(VS.80).aspx
IEnumerator メンバ
http://msdn2.microsoft.com/ja-jp/library/system.collections.ienumerator_members(VS.80).aspx
Understanding Classic COM Interoperability With .NET Applications – The Code Project – .NET
http://www.codeproject.com/dotnet/cominterop.asp#COMCollections
英文だけど記事として秀逸。なぜこれと同等の文書がMSDN Libに無い。。

コメントを残す