C# では ArrayList と Hashtable は(基本的に)非推奨です。
Java は動的に要素を追加したりするのに(割と古い話ですが)ArrayList<E> を使用しますが C# で同等の機能は List<T> クラスであり ArrayList クラスではありません。同様に Java でキーと値の組み合わせを管理する連想配列を使用する場合 HashTable<K, V> クラスがありますが、C# で同等の機能は Dictionary<TKey, TValue> クラスとなっています。
C# のコレクションは ArrayList を使いましょうとする説明がたまにありますが C# で ArrayList や HashTable の使用は推奨できません。代わりに List, Dictionary クラスを使用しましょう
ArrayList や Hashtable は C# にジェネリックが導入される以前の .NET FrameWork からの機能で、割と互換性のために残されているような状態です。新規にコードを書くときは際はそれぞれに対応する List<T> や Dictionary<TKey, TValue> があるのでそちらを使用します。それぞれ同様の機能かつ、ジェネリックによる型指定で安全に利用できます。
特に、入れる値の型が色々あるといったケース以外ではこちらを使用します。System.Collections 名前空間にあるクラスは割と上記のような理由でかなり古いクラス群のなので、System.Collections.Generic にある型を使用します。
非推奨の型(System.Collections) | 新しい型(System.Collections.Generic) | 説明 |
---|---|---|
ArrayList | List<T> | 動的配列として利用できる |
Hashtable | Dictionary<TKey, TValue> | キーと値をペアで管理できる連想配列 |
ArrayListやHashtableが非推奨な理由
ボクシング・アンボクシングでパフォーマンスが低下する
C# の ArrayList や Hashtableは、なんでも入れられる object 型の入れ物になっています。ここに int や byte 等のプリミティブ型を 入れる場合 int → object → int という型変換(ボックス化・アンボックス化)が発生すると変換が挟まってパフォーマンスが低下します。
以下のような単純な使用についても3倍ほど ArrayList が遅くなります。
public static void Main(string[] args) { var r = new Random(); var sw1 = new Stopwatch(); var sw2 = new Stopwatch(); var aList = new ArrayList(); var glist = new List<int>(); for (int i = 0; i < 1000000; i++) { int p = r.Next(); sw1.Start(); // ArrayList に追加する時間を計測 aList.Add(p); sw1.Stop(); sw2.Start(); // List<int> に追加する時間を計測 glist.Add(p); sw2.Stop(); } Console.WriteLine($"Time1 : {sw1.Elapsed}"); Console.WriteLine($"Time2 : {sw2.Elapsed}"); // > Time1: 00:00:00.0992377 ★★★遅い!!! // > Time2: 00:00:00.0372167 }
ちなみに、List や Dictionary でも以下のように宣言すれば ArrayList や Hashtable と同じように使用できます。
var asArrayList = new List<object>(); var asHashtable = new Ditionary<object, object>();
内容の型チェックが毎回必要
object 型で任意の型の値がコレクション内に入っていると、取り出して内容を使用する際に目的の型がどうかチェックしないといけません。リストに入れるデータ型を制限することができないため、想定外の値が入っている可能性を常に考慮しないとキャスト時に例外が発生したりします。
// このように何でも入れられる var alist = new ArrayList() { new object(), 100, 1.275, TimeSpan.FromDays(1), };
このようにデータを入れられてしまうと使用時にかなり困ると思いますが、こうするメリットは全くないように思います。
List<T>、Dictionary<Tkey, TValue>を使いましょう
とにかく ArrayList と HashTabel を使おうと思った場合、代替の List<T>, Dictionary<Tkey, TValue>を使いましょう。
また、System.Collections 名前空間のクラスは可能な限り System.Collection.Generic 名前空間に置き換えられないか検討しましょう。