[C#] ジェネリック(generic)とはなんぞや

C#で動的配列を使いたい時に、ネットで調べると、ArrayListList <t> が、選択肢にあがる。
ハッシュテーブルだと、 HashtableDictionary<TKey, TValue> があがる。

今まで、さほど何も考えず使っていたが、ちょっと使うことが多くなったのでざっくり調べてみた。

結論だけ先に書くと、
「今後は ArrayListは使うな、List<T>を使え、HashTableを使うな、Dictionary<T>を使え。」
ってことだった。
他にも SortedList<T> とかあるんだけど、とにかく <T> とついた物を使っていきましょー。
らしい。

んでは、なぜかをざっくり解説。

今回は双方向Listを例にとって説明する。
Listというのは、追加、削除、並び替えを実現できるアルゴリズム(手段・方法)を実装したものである。

その中身は、以下の3つのデータで実装されている。
・自身のデータ
・前のデータのアドレス
・次のデータのアドレス
詳しくは下記のサイト様が分かりやすい。
http://ufcpp.net/study/algorithm/col_blist.html

んで、C#は静的型付け言語と言われ、早い話、PHPやJavaScriptと違ってしっかり型を宣言する言語である。
だから、上のようなリストを使う場合、使用する型ごとにListクラスを用意しなければならない。
int型のList、string型のList、自分で作ったクラスのList。
だけど、そんなメンドクサイことやってられないから、誰かが考えた。
「C#では、すべてのクラスや文字列等の参照型はObjectクラスを継承するんだから・・、ObjectクラスでList作っておけば、全部つっこめるじゃん!」
「intやdoubleは値型で、参照するタイプじゃないけど、無理やりObject型にして(ボックス化)、代入しよう!」
と。

そして、ArrayListというクラスが生まれた。
どんな物を入れてもObject型に変換されるので、何でも入れれる。
反面、取り出す時は(string)といった感じでキャストが必須になりはしたが、自分でListのアルゴリズムを実装する手間はなくなった。

しかし、この方法には問題があった。
何でも入れれるが、間違った型を入れることもできる。(stringにintとか)
コンパイルする時点ではエラーにならず、実行中に型が違いますってエラーになる。
自分で何の型を入れたかしっかり覚えとかないと、バグの元になる。
もはや、静的型言語のメリットがない。
さらに、毎回Object型にキャストされるので、かなり無駄。
特にボックス化はパフォーマンスよくない。

ってことで、C# 2.0 から実装されたのがジェネリック。
「とりあえずクラスの型はインスタンスを作るコードを書くときに決めるとして、それまで仮の名で置いておこうぜ。」という仕様。
<T>っておいたら、仮の型名とされた。
(TじゃなくてもいいらしいけどTはとにかくつける暗黙のルールらしい)

これで、クラスを作るときは、List<T> という名前で作られて、
いざ new でインスタンス作るときに、 new List<int> とすると、仮の型名はintと置き換えて、コンパイルされる。
なので、キャストもいらないし、型がおかしかったりするとコンパイル時にエラーとなるので、バグの元にもなりにくい。

唯一、なんでも突っ込めるというメリットが無くなったけど、そもそもそんなこと滅多にしないし、やりたければ List<Object> で実現できる。

そして、結果、ArrayListはわざわざ使うメリットが全くなくなったということ。

らしい!
ざっくりとしか理解してないから、間違っているかも。
(経緯やセリフも想像です。)

参考
http://www.atmarkit.co.jp/ait/articles/0602/11/news011.html

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>