技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

.NET を理解する5

ジェネリックコレクション

ジェネリックコレクションは、System.Collection.Generic に存在する、Generic 機能を利用したコレクションクラスです。
これは、対応する非ジェネリックコレクションに比べて、タイプセーフかつ高速に動作します。

これには

  • List
  • Dictionary
  • Queue
  • Stack
  • SortedList
  • SortedDictionary

等があり、これらは非ジェネリックのそれぞれのクラスに対応します。

実装の違い

Generic を理解し、Collection を知っていれば、使うことは難しくないでしょう。
ここでは、同じ Generic を持つ Java と、元となった Template を実装する C++ とを比較してみます。

1.実装方法

これは明らかに差があります。

  • C#(.NET) : Generic の為の拡張命令をアセンブリに持ちます。object 型へのキャスト等の処理が行われない為、高速です(C++には負けますけど、、、)。
  • Java(JVM) : Java5 ではコンパイラシンタックスシュガー(糖衣構文)で実装されます。object 型への変換、元の型へのキャストを、暗黙的に埋め込みます。実行速度は従来のものと変わりません。
  • C++(ネイティブ) : typedef や define マクロ同様に、コンパイル時に型を埋め込む形でコンパイルします。実行速度は最速ですが、ファイルサイズが大きくなる、ライブラリをソースで配布するしかないという欠点もあります。

2.型安全性

  • C# : Generic 指定の異なる型は、完全に違う型として認識されます。継承関係のある型のジェネリックに関しては、.NET4.0 以降でジェネリック型のキャストが可能です。
  • Java : Java6 以降でかなり進化しました。コンパイラレベルでチェックされ、互換性のない型を弾けるようになっています。
  • C++ : 完全に別の型としてコンパイルされます。

3.互換性
.NET3.5 からは、下位のライブラリと共存できるようになりました。

  • Java : コードレベルでの互換性はありません。class ファイルに、コンパイルバージョンが含まれており、下位のランタイムででは実行できません。ただし、上位のランタイムは、下位のクラスを読み込んで実行できます(非ジェネリックなライブラリを呼ぶことは可能

)。

  • C++ :ネイティブコードに互換性は、、、、

補足すると、C++ の場合はある種のマクロとして展開、コンパイルされますので、template 指定に int やポインタ、関数ポインタであろうと指定することができます。
それはそれで可読性や保守性はどうだろう?という疑問はあるでしょうが、自由度は最大でしょう。
たまに、たらいまわし関数をコンパイル時に template で展開計算して実行時の計算コストを 0 にするとかいう神がかった荒業をする人もいます。