まず、 ではなく を必ず使用する必要がありDictionary<TKey, TValue>
ますHashTable
。非ジェネリック コレクション型は、実際には下位互換性のために存在します。新しいコードにはジェネリック型を使用することをお勧めします。
特定の問題に関しては、.NET ディクショナリの型で許可されるキーは 1 つだけであることに注意してください。実際、これは一般的なディクショナリ コレクションでは一般的です。コレクション内の各エントリは、1 つのキーと値のペアです。
ただし、3 つのキー値を組み合わせて 1 つのオブジェクト値にし、代わりにそれをキーとして使用できます。実際、.NET はTuple
それを実現するためのさまざまなクラスを提供します。型パラメーターの数ごと、つまりオブジェクト内のアイテムの数ごとに異なるクラスです。さらに、これらのクラスはすべて、辞書のキーとして使用するための適切な比較とハッシュを実装しています。
これを質問に適用すると、本当にやりたいことに応じて、いくつかのオプションがあります。残念ながら、あなたが何をしたいのかははっきりしていません。:(
キー値のトリプレットごとに最大 3 つの値しか持たない場合は、コメンターの Mephy からの提案は問題ないと思います。コレクションを宣言して、次のように初期化できます。
Dictionary<Tuple<int, int, int>, Tuple<string, string, string>> collection =
new Dictionary<Tuple<int, int, int>, Tuple<string, string, string>>
{
{ Tuple.Create(0, 0, 0), Tuple.Create("a", "b", "c") },
{ Tuple.Create(0, 0, 1), Tuple.Create("d", "e", "f") },
{ Tuple.Create(0, 1, 1), Tuple.Create("g", "h", null) },
};
null
ディクショナリの値のタプルに欠損値があることを示すために使用されることに注意してください。
ただし、文字通りリスト オブジェクトを値として使用する場合は、代わりに次のようにすることもできます。
Dictionary<Tuple<int, int, int>, List<string>> collection =
new Dictionary<Tuple<int, int, int>, List<string>>
{
{ Tuple.Create(0, 0, 0), new List<string> { "a", "b", "c"} },
{ Tuple.Create(0, 0, 0), new List<string> { "d", "e", "f"} },
{ Tuple.Create(0, 0, 0), new List<string> { "g", "h" } },
};
上記をキーと値のペアのリストとして扱う限り、任意の .NET コレクション型と同様に、値の列挙として扱うことがDictionary<TKey, TValue>
できます。したがって、たとえば次のようなことができます。IEnumerable<KeyValuePair<TKey, TValue>>
TKey
TValue
foreach (KeyValuePair<Tuple<int, int, int>, List<string>> kvp in collection)
{
// here, kvp.Key will have the Tuple<int, int, int> key value
// for the dictionary entry, while kvp.Value will have the
// List<string> value for the same entry.
}
.NET でのディクショナリ型の列挙の順序は定義されていないことに注意してください。要素が特定の順序 (追加された順序など) で返されるという保証はありません。特定の順序が必要な場合は、何らかの方法でそれを課す必要があります。
最後に、上記の例のKeyValuePair<TKey, TValue>
タイプに注意してください。Tuple...
実際、これはタプルの特殊なケースにすぎません (ただし、.NETの実際のクラスより前の日付です)。つまり、キーと値のペアを格納する目的で特別に設計されたカスタム クラスです。
必要に応じて、そのような型を自分で宣言して、辞書のキーとして機能させることができます。Tuple...
これには、特定の読み取り可能な型の名前を指定できるという利点があり、もちろん、クラスの処理に伴う冗長性の一部を回避できるという利点があります(Tuple.Create()
ジェネリック メソッドは役立ちますが、宣言は依然として扱いにくくなる可能性があります)。 )。これを行うには、当然、独自の比較およびハッシュ コードを作成する必要があります。
Tuple...
必要なクラスを継承するクラスを作成し、コンストラクターのみを実装する (初期化パラメーターを基本コンストラクターに渡す) ことによって、妥協点を見つけることができます。
class CustomKey : Tuple<int, int, int>
{
public CustomKey(int i1, int i2, int i3) : base(i1, i2, i3) { }
}
または、単にディレクティブを使用Tuple...
してモジュール内の型にエイリアスを設定し、型にローカルで使用可能な、より読みやすい名前を付けます。たとえば、次のようになります。using
Tuple...
using CustomKey = System.Tuple<int, int, int>;
前者を使用すると、プロジェクト内のどこでも読み取り可能な名前に簡単にアクセスできますが、(非常に短い) クラスを実装する必要があります。後者は作業が少なくて済みますが、単一のソース ファイルにのみ適用されます。