読者です 読者をやめる 読者になる 読者になる

謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

.NET を理解する5

.NET C# Tips
ジェネリックコレクション

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

これには

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

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

実装の違い

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

1.実装方法

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

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

2.型安全性

  • C# : Generic 指定の異なる型は、完全に違う型として認識されます。継承関係のある型のジェネリックに関しては、.NET4.0 以降でジェネリック型のキャストが可能です。
  • Java : Generic 指定が異なっても、内部的には object なので、型を区別できません。(コンパイラのエラー頼り)
  • C++ : 完全に別の型としてコンパイルされます。

3.互換性

  • C# : .NET1.1 以下(Generic未対応)のランタイムと、.NET2.0 以降では互換性がありません。
  • Java : 互換性を考慮している為、Java6.0 新規追加API等を使わない限り、Generic を使っても下位JVMで動作します。
  • C++ :ネイティブコードに互換性は、、、、

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