HOWTO · Csharp

C# での辞書とハッシュテーブル

このガイドでは、C# での辞書とハッシュテーブルの違いについて説明します。どちらがいいですか?

このページの内容

このガイドでは、C# の辞書Hashtable の違いについて説明します。

これらのコレクションのどれがより良く、好まれているかを理解するには、それらの基本を理解する必要があります。それでは、これら 2つのコレクションに関連する構文、特性、機能、およびメソッドについて見ていきましょう。

C# で作業する場合、どちらを選択する必要がありますか?どちらが良いですか?

これらの質問はすべて以下で回答されます。飛び込みましょう!

C# の辞書

辞書は一般的なコレクションです。データはキーと値のペアで格納され、このコレクションには特定の順序はありません。

辞書の構文は次のとおりです。

Dictionary<TKey, TValue>

データ値とそのキーを渡します。辞書の特徴を見ていきましょう。

C# の辞書の特徴

  1. キーと値のペアを格納します。
  2. その名前空間は System.Collections.Generic です。
  3. 辞書のキーは null であってはならず、一意である必要があります。
  4. ただし、値は null で重複している可能性があります。
  5. 対応するキー(myDictionary[key] など)を使用してデータ値にアクセスできます。
  6. すべての要素は KeyValuePair<TKey, TValue> と見なされます。

C# で辞書を作成する

保存できる値のタイプとそれに対応するキーを渡すことにより、C# で辞書を作成できます。次のコードを見て、辞書を作成する方法を確認してください。

IDictionary<int, string> rollno_names = new Dictionary<int, string>();
rollno_names.Add(1, "Ali");  // adding a key/value using the Add() method
rollno_names.Add(2, "Haider");
rollno_names.Add(3, "Saad");

// The following throws runtime exception: key already added.
// rollno_names.Add(3, "Rafay");

foreach (KeyValuePair<int, string> i in rollno_names)
  Console.WriteLine("Key: {0}, Value: {1}", i.Key, i.Value);

// creating a dictionary using collection-initializer syntax
var countries = new Dictionary<string, string>() {
  { "UK", "United Kingdom" }, { "USA", "United States of America" }, { "PK", "Pakistan" }
};

foreach (var j in countries) Console.WriteLine("Key: {0}, Value: {1}", j.Key, j.Value);

上記のコードでは、rollno_names辞書であり、次のように、キーデータ型として int を、値データ型として string を使用しています。

Dictionary<int, string>

この特定の辞書は、int キーと文字列値を格納できます。2 番目の辞書は、コレクション初期化子によって作成された国のものです。

キーと値はどちらも文字列データ型です。Key-Value を複製して null にしようとすると、実行時例外が発生します。

C# の辞書要素にアクセスする

インデクサーを使用して、Dictionary 要素にアクセスできます。対応する値にアクセスするには、各キーを指定する必要があります。

ElementAt() は、キーと値のペアを取得するためのもう 1つのアプローチです。次のコードを見てください。

var countries = new Dictionary<string, string>() {
  { "UK", "UnitedKingdom" }, { "USA", "United State of America" }, { "PK", "Pakistan" }
};

Console.WriteLine(countries["UK"]);   // prints value of UK key
Console.WriteLine(countries["USA"]);  // prints value of USA key
// Console.WriteLine(countries["France"]); // runtime exception: key does not exist

// use ContainsKey() to check for the unknown key
if (countries.ContainsKey("France")) {
  Console.WriteLine(countries["France"]);
}

// use TryGetValue() to get a value of the unknown key
string result;

if (countries.TryGetValue("France", out result)) {
  Console.WriteLine(result);
}

// use ElementAt() to retrieve the key-value pair using the index
for (int i = 0; i < countries.Count; i++) {
  Console.WriteLine("Key: {0}, Value: {1}", countries.ElementAt(i).Key,
                    countries.ElementAt(i).Value);
}

上記のコードでは、フランスを含むキーと値のペアがないことがわかります。したがって、上記のコードは実行時例外を発生させます。

C# の辞書要素を更新する

インデクサーでキーを指定することにより、キーの値を変更/更新できます。辞書でキーが見つからない場合、KeyNotFoundException 例外がスローされます。したがって、不明なキーにアクセスする前に、ContainsKey() 関数を使用してください。

次のコードを見てください。

var countries = new Dictionary<string, string>() { { "UK", "London, Manchester, Birmingham" },
                                                   { "USA", "Chicago, New York, Washington" },
                                                   { "PK", "Pakistan" } };

countries["UK"] = "Europe";    // update value of UK key
countries["USA"] = "America";  // update value of USA key
// countries["France"] = "Western Europe"; //throws run-time exception: KeyNotFoundException

if (countries.ContainsKey("France")) {
  countries["France"] = "Western Europe";
}

C# の辞書要素を削除する

Dictionary にすでに存在するキーと値のペアは、Remove() メソッドを使用して削除されます。すべての Dictionary 要素は、Clear() メソッドを使用して削除されます。

var countries = new Dictionary<string, string>() {
  { "UK", "UnitedKingdom" }, { "USA", "United state of America" }, { "PK", "Pakistan" }
};

countries.Remove("UK");  // removes UK
// countries.Remove("France"); //throws run-time exception: KeyNotFoundException

if (countries.ContainsKey("France")) {  // check key before removing it
  countries.Remove("France");
}

countries.Clear();

C# のハッシュテーブル

辞書とは異なり、Hashtable は非ジェネリックコレクションです。また、キーと値のペアも格納します。

各キーのハッシュコードを計算し、それを個別の内部バケットに格納することで、値にアクセスするときに提供されたキーのハッシュコードを照合することにより、ルックアップを改善します。Hashtable のいくつかの特徴を見てみましょう。

C# のハッシュテーブルの特徴

  1. キーと値のペアは Hashtable に保持されます。
  2. 名前空間 SystemCollection に属しています。
  3. IDictionary インターフェースが実装されています。
  4. キーはヌルにすることはできず、区別する必要があります。
  5. 値が重複しているか null である可能性があります。
  6. 値は、Hashtable[key] のように、インデクサーに関連するキーを提供することで取得できます。
  7. DictionaryEntry オブジェクトは、要素を格納するために使用されます。

C# でハッシュテーブルを作成する

Hashtable の作成を理解するには、次の自明のコードを見てください。

`Hashtable` rollno_names = new `Hashtable`();
rollno_names.Add(1, "Ali");  // adding a key/value using the Add() method
rollno_names.Add(2, "Haider");
rollno_names.Add(3, "Saad");

// The following throws runtime exception: key already added.
// rollno_names.Add(3, "Rafay");

foreach (DictionaryEntry i in rollno_names)
  Console.WriteLine("Key: {0}, Value: {1}", i.Key, i.Value);

// creating a `Hashtable` using collection-initializer syntax
var countries = new `Hashtable`() {
  { "UK", "UnitedKingdom" }, { "USA", "United State of America" }, { "PK", "Pakistan" }
};

foreach (DictionaryEntry j in countries) Console.WriteLine("Key: {0}, Value: {1}", j.Key, j.Value);

辞書と同じように Hashtable を作成できます。唯一の違いは、ジェネリックではないため、キーのデータ型とそれに対応する値を指定する必要がないことです。

C# のハッシュテーブルに辞書を追加する

Dictionary のオブジェクトを作成できます。Hashtable の作成中にそのオブジェクトを渡すだけで、Hashtable 内に Dictionary のキーと値のペアを追加できます。

C# でハッシュテーブルを更新する

インデクサーにキーを入力することにより、Hashtable から既存のキーの値を取得できます。Hashtable は非ジェネリックコレクション(キーと値の両方にデータ型がないことを意味します)であるため、値を取得するときに文字列に型キャストする必要があります。

次のコードを見てください。

// creating a Hashtable using collection-initializer syntax
var countries = new Hashtable() {
  { { "UK", "UnitedKingdom" }, { "USA", "United State of America" }, { "PK", "Pakistan" } };

string countrynameUK = (string)countries["UK"];    // cast to string
string countrynameUSA = (string)countries["USA"];  // cast to string

Console.WriteLine(countrynameUK);
Console.WriteLine(countrynameUSA);

countries["UK"] = "Euorpe";    // update value of UK key
countries["USA"] = "America";  // update value of USA key

if (!countries.ContainsKey("France")) {
  countries["France"] = "Western Euorpe";
}

C# のハッシュテーブルから要素を削除する

Hashtable の指定されたキーと値のペアは、Remove() メソッドを使用して削除されます。提供されたキーが Hashtable に存在しない場合、KeyNotfoundException 例外がスローされます。したがって、キーを削除する前に、ContainsKey() メソッドを使用して、キーがすでに存在するかどうかを確認してください。

Clear() 関数を使用して、すべてのアイテムを一度に削除します。

var countries = new Hashtable() {
  { "UK", "UnitedKingdom" }, { "USA", "United State of America" }, { "PK", "Pakistan" }
};

countries.Remove("UK");  // removes UK
// countries.Remove("France"); //throws run-time exception: KeyNotFoundException

if (countries.ContainsKey("France")) {  // check key before removing it
  countries.Remove("France");
}

countries.Clear();  // removes all elements

C# の辞書とハッシュテーブル

Dictionary Hashtable
存在しないキーを検出しようとすると、例外が返されるか、例外がスローされます。 存在しないキーを検出しようとすると、null が返されます。
ボクシングとアンボクシングがないため、Hashtable よりも高速です。 ボクシングとアンボクシングが必要なため、辞書よりも時間がかかります。
スレッドセーフは、パブリックスタティックメンバーでのみ使用できます。 Hashtable のメンバーはすべてスレッドセーフであり、
Dictionary はジェネリック型であるため、任意のデータ型を使用できます(作成時に、キーと値の両方のデータ型を指定する必要があります)。 ジェネリックタイプではありません。
強く型付けされたキーと値を使用した Hashtable の実装は、ディクショナリと呼ばれます。 Hashtable は柔軟に型指定されたデータ構造であるため、任意のキーと値の型を追加できます。

これらの事実に基づいて、Hashtable よりも辞書の方が好ましいと言えます。Dictionary<TKey, TValue> に任意のランダムなアイテムを挿入でき、取り出した値をキャストする必要がないため、型の安全性が得られます。