2013-08-06T22:30:35の更新内容

programming/netfx/collections/2_generic_2_dictionary/index.wiki.txt

current previous
158,7 158,7
 
   場所 Sample.Main()
   場所 Sample.Main()
 
}}
}}
 

        

        
~
この動作は、存在しないキーに対してnull/Nothingが返される[[Hashtable>programming/netfx/collections/1_nongeneric_2_hashtable#Hashtable]]とは異なるので注意してください。 Dictionaryでは、インデクサで取得した値からキーが存在するかどうかを確認することはできません。 事前にキーが存在するかどうかを確かめるには[[ContainsKeyメソッド>#ContainsKeyContainsValue]]を使うことが出来ます。
事前にキーが存在するかどうかを確かめるには[[ContainsKeyメソッド>#ContainsKeyContainsValue]]を使うことが出来ます。
 

        

        
 
**要素の追加
**要素の追加
 
既に例に挙げた通りインデクサでキーを指定することでDictionaryに要素を設定(追加)することができますが、これとは別に&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Add){Addメソッド};を使うことでもDictionaryに要素を追加することが出来ます。
既に例に挙げた通りインデクサでキーを指定することでDictionaryに要素を設定(追加)することができますが、これとは別に&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Add){Addメソッド};を使うことでもDictionaryに要素を追加することが出来ます。
281,61 281,7
 
   場所 Sample.Main()
   場所 Sample.Main()
 
}}
}}
 

        

        
~
このように、インデクサでは指定されたキーが存在しているかどうかに関わらず値が上書きされて設定されるのに対し、Addメソッドではキーが既に存在しているかを検査した上で値の追加が行われます。 事前にキーが存在するかどうかを確かめるには[[ContainsKeyメソッド>#ContainsKeyContainsValue]]を使います。
このように、インデクサでは指定されたキーが存在しているかどうかに関わらず値が上書きされて設定されるのに対し、Addメソッドではキーが既に存在しているかを検査した上で値の追加が行われます。
+

          
+

          
+
**コレクション初期化子
+
Dictionaryを使用する場合、インスタンスの作成後に要素の追加を行う場合が多々あります。 ''コレクション初期化子''を使うと、インスタンスの作成と要素の追加を同時に行うことができます。 コレクション初期化子はC# 3.0(Visual C# 2008)以降、VB 10(Visual Basic 2010)以降でサポートされます。
+

          
+
#tabpage(codelang=cs,container-title=コレクション初期化子を使ったインスタンスの初期化)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // コレクション初期化子を使ってインスタンスの作成と要素の追加を行う
+
    Dictionary<string, int> dict = new Dictionary<string, int>() {
+
      {"foo", 16},
+
      {"bar", 72},
+
      {"baz", 42},
+
    };
+

          
+
    Console.WriteLine("foo = {0}", dict["foo"]);
+
    Console.WriteLine("Count = {0}", dict.Count);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' コレクション初期化子を使ってインスタンスの作成と要素の追加を行う
+
    Dim dict As New Dictionary(Of String, Integer)() From {
+
      {"foo", 16},
+
      {"bar", 72},
+
      {"baz", 42}
+
    }
+

          
+
    Console.WriteLine("foo = {0}", dict("foo"))
+
    Console.WriteLine("Count = {0}", dict.Count)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
foo = 16
+
Count = 3
+
}}
+

          
+
コレクション初期化子では、``{ {&var{キー1};, &var{値1};}, {&var{キー2};, &var{値2};} }``のように追加する要素をペア毎に中括弧で括って記述します。 RubyやPerlのハッシュで使われる``{&var{キー1}; => &var{値1};, &var{キー2}; => &var{値2};}``といった形式はコレクション初期化子ではサポートされません。
+

          
 

        

        
 
**要素の削除
**要素の削除
 
Dictionaryから要素を削除する場合は、&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Remove){Removeメソッド};を使います。 このメソッドでは、指定されたキーを持つ要素をDictionaryから削除し、戻り値として実際に削除に成功したかどうかが返さます。 Addメソッドとは異なりRemoveメソッドに指定したキーを持つ要素が存在しない場合でも例外はスローされません(戻り値としてfalseが返されます)。
Dictionaryから要素を削除する場合は、&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Remove){Removeメソッド};を使います。 このメソッドでは、指定されたキーを持つ要素をDictionaryから削除し、戻り値として実際に削除に成功したかどうかが返さます。 Addメソッドとは異なりRemoveメソッドに指定したキーを持つ要素が存在しない場合でも例外はスローされません(戻り値としてfalseが返されます)。
416,9 362,9
 
Count = 1
Count = 1
 
}}
}}
 

        

        
~
なお、インデクサを使って値にnull/Nothingを設定しても''要素自体を削除することはできません''。 この場合、指定されたキーに対応する値としてnull/Nothingが設定されるだけで、要素の数は変わりません。
なお、インデクサを使って値にnull/Nothingを設定しても要素自体を削除することができません。 この場合、指定されたキーに対応する値としてnull/Nothingが設定されるだけで、要素の数は変わりません。
 

        

        
~
Dictionary内のすべての要素を削除するには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Clear){Clearメソッド};を使うことが出来ます。
また、Dictionary内のすべての要素を削除するには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.Clear){Clearメソッド};を使うことが出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
473,171 419,6
 
Count = 0
Count = 0
 
}}
}}
 

        

        
+

          
+
**値に対する変更
+
値に構造体を格納するようにしたDictionaryで構造体のプロパティやフィールドだけを変更しようとする場合は注意が必要です。 例えば、次のようなコードはコンパイルエラーとなります。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
// Dictionaryに格納する構造体
+
struct S
+
{
+
  public int F;
+

          
+
  public S(int f)
+
  {
+
    F = f;
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, S> dict = new Dictionary<string, S>();
+

          
+
    // フィールドFに値3を設定した構造体を格納
+
    dict["foo"] = new S(3);
+

          
+
    // キー"foo"の構造体フィールドの値を変更したいが、コンパイルエラーとなる
+
    dict["foo"].F = 16;
+
    // error CS1612: 変数ではないため、'System.Collections.Generic.Dictionary<string,S>.this[string]'の戻り値を変更できません。
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
' Dictionaryに格納する構造体
+
Structure S
+
  Public F As Integer
+

          
+
  Public Sub New(ByVal val As Integer)
+
    F = val
+
  End Sub
+
End Structure
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, S)()
+

          
+
    ' フィールドFに値3を設定した構造体を格納
+
    dict("foo") = New S(3)
+

          
+
    ' キー"foo"の構造体フィールドの値を変更したいが、コンパイルエラーとなる
+
    dict("foo").F = 16
+
    ' error BC30068: Expression は値であるため、代入式のターゲットにすることはできません。
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
このような操作を行いたい場合は、いったんDictionaryから一時変数に構造体をコピーし、値を変更してから再度Dictionaryに格納するようにします。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
// Dictionaryに格納する構造体
+
struct S
+
{
+
  public int F;
+

          
+
  public S(int f)
+
  {
+
    F = f;
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, S> dict = new Dictionary<string, S>();
+

          
+
    // フィールドFに値3を設定した構造体を格納
+
    dict["foo"] = new S(3);
+

          
+
    // Dictionaryに格納した構造体フィールドの値を参照
+
    Console.WriteLine("dict[\"foo\"].F = {0}", dict["foo"].F);
+

          
+
    // フィールドの値を変更したい構造体を一時変数にコピーする
+
    S tmp = dict["foo"];
+

          
+
    // 一時変数に代入した構造体のフィールドの値を変更する
+
    tmp.F = 16;
+

          
+
    // 変更した構造体を再度Dictionaryに格納する
+
    dict["foo"] = tmp;
+

          
+
    // Dictionaryに格納した構造体フィールドの値を参照
+
    Console.WriteLine("dict[\"foo\"].F = {0}", dict["foo"].F);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
' Dictionaryに格納する構造体
+
Structure S
+
  Public F As Integer
+

          
+
  Public Sub New(ByVal val As Integer)
+
    F = val
+
  End Sub
+
End Structure
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, S)()
+

          
+
    ' フィールドFに値3を設定した構造体を格納
+
    dict("foo") = New S(3)
+

          
+
    ' Dictionaryに格納した構造体フィールドの値を参照
+
    Console.WriteLine("dict(""foo"").F = {0}", dict("foo").F)
+

          
+
    ' フィールドの値を変更したい構造体を一時変数にコピーする
+
    Dim tmp As S = dict("foo")
+

          
+
    ' 一時変数に代入した構造体のフィールドの値を変更する
+
    tmp.F = 16
+

          
+
    ' 変更した構造体を再度Dictionaryに格納する
+
    dict("foo") = tmp
+

          
+
    ' Dictionaryに格納した構造体フィールドの値を参照
+
    Console.WriteLine("dict(""foo"").F = {0}", dict("foo").F)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
dict("foo").F = 3
+
dict("foo").F = 16
+
}}
+

          
+
なお、構造体ではなくクラスの場合はこのような操作を行う必要はありません。 この違いは型が値型か参照型かによって決まります。 詳しくは[[programming/netfx/cloning]]を参照してください。
+

          
+

          
+

          
+

          
+

          
+

          
+

          
+

          
+

          
+

          
+

          
 
**要素の列挙 [#Dictionary_Enumeration]
**要素の列挙 [#Dictionary_Enumeration]
 
***DictionaryとKeyValuePair
***DictionaryとKeyValuePair
 
列挙について解説する前に、Dictionaryの内部構造と&msdn(netfx,type,System.Collections.Generic.KeyValuePair`2){KeyValuePair構造体};について触れておきます。 Dictionaryでは、要素を格納する際、キーと値の組み合わせをKeyValuePairとして格納します。 KeyValuePairはその名の通り、キーとそれに対応する値のペアを表す構造体です。 Dictionaryの内部では、キーと値の組み合わせはKeyValuePairで管理されます。
列挙について解説する前に、Dictionaryの内部構造と&msdn(netfx,type,System.Collections.Generic.KeyValuePair`2){KeyValuePair構造体};について触れておきます。 Dictionaryでは、要素を格納する際、キーと値の組み合わせをKeyValuePairとして格納します。 KeyValuePairはその名の通り、キーとそれに対応する値のペアを表す構造体です。 Dictionaryの内部では、キーと値の組み合わせはKeyValuePairで管理されます。
749,19 530,13
 
42
42
 
}}
}}
 

        

        
-
***要素の列挙と順序
-
Dictionaryは''順序を持たないコレクション''であるため、Dictionaryの要素を列挙する場合、List等とは異なり''必ずしも追加した順で列挙されるとは限らない''点に注意が必要です。 また、順序を持たないためインデックスを指定してキー・値を参照することも出来ないため、for文による列挙は行えません。 インデックスを使った操作を行いたい場合は、次の例のように一旦DictionaryからListに変換したり、キーと値を別の配列・コレクションにコピーしてから列挙する、といった方法を取る必要があります。
 

        

        
~
***要素の列挙と順序 [#ordered_enumeration]
#tabpage(codelang=cs,container-title=DictionaryからListに変換して列挙する)
+
Dictionaryは''順序を持たないコレクション''であるため、Dictionaryの要素を列挙する場合、List等とは異なり''必ずしも追加した順で列挙されるとは限らない''点に注意が必要です。 そのため、foreach文でDictionaryの列挙を行う場合は、列挙される順序に依存しないように処理を記述する必要があります。
+

          
+
列挙される順序が意味を持つ場合は、Dictionaryの代わりに[[SortedList・SortedDictionary>programming/netfx/collections/2_generic_3_sortedlist_sorteddictionary]]を使うことができます。 SortedList・SortedDictionaryでは、常に一定の順序で列挙されることが保証されます。 また、非ジェネリックコレクションである&msdn(netfx,type,System.Collections.Specialized.OrderedDictionary){OrderedDictionaryクラス};では、要素を追加した順序が維持され追加された順で列挙されます。
+

          
+
このほか、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.OrderBy){OrderBy};を使うことにより、順序を定義して要素の列挙を行うこともできます。
+

          
+
#tabpage(codelang=cs,container-title=OrderByメソッドを使って列挙順を定義する例)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
+
using System.Linq;
 

        

        
 
class Sample
class Sample
 
{
{
773,10 548,13
 
    dict["bar"] = 72;
    dict["bar"] = 72;
 
    dict["baz"] = 42;
    dict["baz"] = 42;
 

        

        
~
    // 値の小さい順(昇順)でDictionaryに格納されている要素を列挙
    // Dictionaryと同じ内容を含むListを作成
~
    foreach (KeyValuePair<string, int> pair in dict.OrderBy(p => p.Value))
    List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(dict);
-

          
-
    // for文を使って作成したListを列挙
-
    for (int i = 0; i < list.Count; i++)
 
    {
    {
~
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value);
      Console.WriteLine("{0} : {1} => {2}", i, list[i].Key, list[i].Value);
 
    }
    }
 
  }
  }
 
}
}
785,7 563,6
 
#code{{
#code{{
 
Imports System
Imports System
 
Imports System.Collections.Generic
Imports System.Collections.Generic
+
Imports System.Linq
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
795,9 572,12
 
    dict("bar") = 72
    dict("bar") = 72
 
    dict("baz") = 42
    dict("baz") = 42
 

        

        
~
    ' 値の小さい順(昇順)でDictionaryに格納されている要素を列挙
    ' Dictionaryと同じ内容を含むListを作成
~
    For Each pair As KeyValuePair(Of String, Integer) In dict.OrderBy(Function(p) p.Value)
    Dim list As New List(Of KeyValuePair(Of String, Integer))(dict)
~
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value)

          
-
    ' Forステートメントを使って作成したListを列挙
-
    For i As Integer = 0 To list.Count - 1
-
      Console.WriteLine("{0} : {1} => {2}", i, list(i).Key, list(i).Value)
 
    Next
    Next
 
  End Sub
  End Sub
 
End Class
End Class
805,18 585,14
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
foo => 16
0 : foo => 16
~
baz => 42
1 : bar => 72
~
bar => 72
2 : baz => 42
 
}}
}}
 

        

        
~
OrderByメソッドについて詳しくは[[programming/netfx/sorting/0_basictypes#Enumerable.OrderBy]]で解説しています。
次の例では、CopyToメソッドを使って、キーと値を個別の配列にコピーしてから列挙しています。
+

          
+

          
+
***列挙中の要素の追加・削除
+
Dictionaryをforeach文で列挙している最中に要素の追加や削除などの変更を行おうとすると、例外&msdn(netfx,type,System.InvalidOperationException){InvalidOperationException};がスローされます。
 

        

        
~
#tabpage(codelang=cs,container-title=列挙中の要素の削除)
#tabpage(codelang=cs,container-title=Dictionaryからキーと値を別の配列にコピーして列挙する)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
830,13 606,19
 
    dict["foo"] = 16;
    dict["foo"] = 16;
 
    dict["bar"] = 72;
    dict["bar"] = 72;
 
    dict["baz"] = 42;
    dict["baz"] = 42;
+
    dict["hoge"] = 3;
+
    dict["huga"] = 42;
 

        

        
~
    foreach (KeyValuePair<string, int> pair in dict)
    // キーと値を格納するための配列を作成
-
    string[] keys = new string[dict.Count];
-
    int[] values = new int[dict.Count];
-

          
-
    // キーと値を配列にコピー
-
    dict.Keys.CopyTo(keys, 0);
-
    dict.Values.CopyTo(values, 0);
-

          
-
    // for文を使ってコピーしたキーと値の配列を列挙
-
    for (int i = 0; i < keys.Length; i++)
 
    {
    {
~
      // 値が42の場合は、削除する
      Console.WriteLine("{0} : {1} => {2}", i, keys[i], values[i]);
+
      if (pair.Value == 42) dict.Remove(pair.Key);
 
    }
    }
 
  }
  }
 
}
}
853,12 635,18
 
    dict("foo") = 16
    dict("foo") = 16
 
    dict("bar") = 72
    dict("bar") = 72
 
    dict("baz") = 42
    dict("baz") = 42
+
    dict("hoge") = 3
+
    dict("huga") = 42
 

        

        
~
    For Each pair As KeyValuePair(Of String, Integer) In dict
    ' キーと値を格納するための配列を作成
~
      ' 値が42の場合は、削除する
    Dim keys(dict.Count - 1) As String
~
      If pair.Value = 42 Then dict.Remove(pair.Key)
    Dim values(dict.Count - 1) As Integer
-

          
-
    ' キーと値を配列にコピー
-
    dict.Keys.CopyTo(keys, 0)
-
    dict.Values.CopyTo(values, 0)
-

          
-
    ' Forステートメントを使ってコピーしたキーと値の配列を列挙
-
    For i As Integer = 0 To keys.Length - 1
-
      Console.WriteLine("{0} : {1} => {2}", i, keys(i), values(i))
 
    Next
    Next
 
  End Sub
  End Sub
 
End Class
End Class
866,16 654,15
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
ハンドルされていない例外: System.InvalidOperationException: コレクションが変更されました。列挙操作は実行されない可能性があります。
0 : foo => 16
~
   場所 System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
1 : bar => 72
~
   場所 Sample.Main()
2 : baz => 42
 
}}
}}
 

        

        
~
例外が発生する理由や回避する方法については[[programming/netfx/enumeration#modifying_while_enumerating]]でも解説していますが、Dictionaryクラスではインデックスを指定した列挙操作は行えないため、ここで紹介している方法は適用できません。
***列挙中の要素の追加・削除
-
Dictionaryをforeach文で列挙している最中に要素の追加や削除などの変更を行おうとすると、例外&msdn(netfx,type,System.InvalidOperationException){InvalidOperationException};がスローされます。
 

        

        
~
先の例のように条件に合う要素を検索して削除するといった場合は、列挙による要素の検索と削除を別々のforeach文で行うようにすることでInvalidOperationExceptionの発生を回避することが出来ます。
#tabpage(codelang=cs,container-title=列挙中の要素の削除)
+

          
+
#tabpage(codelang=cs,container-title=要素の検索と削除を別々に行う例)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
889,28 676,11
 
    dict["foo"] = 16;
    dict["foo"] = 16;
 
    dict["bar"] = 72;
    dict["bar"] = 72;
 
    dict["baz"] = 42;
    dict["baz"] = 42;
+
    dict["hoge"] = 3;
+
    dict["huga"] = 42;
+

          
+
    // 削除対象のキーを格納するList
+
    List<string> removeKeys = new List<string>();
 

        

        
 
    foreach (KeyValuePair<string, int> pair in dict)
    foreach (KeyValuePair<string, int> pair in dict)
 
    {
    {
~
      // 値が42の場合は、削除対象としてListにキーを追加
      // 値が42の場合は、削除する
~
      if (pair.Value == 42) removeKeys.Add(pair.Key);
      if (pair.Value == 42) dict.Remove(pair.Key);
+
    }
+

          
+
    // 対象となるキーを持つ要素を削除
+
    foreach (string key in removeKeys)
+
    {
+
      dict.Remove(key);
+
    }
+

          
+
    // 削除後のDictionaryの内容を列挙
+
    foreach (KeyValuePair<string, int> pair in dict)
+
    {
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value);
 
    }
    }
 
  }
  }
 
}
}
927,25 697,10
 
    dict("foo") = 16
    dict("foo") = 16
 
    dict("bar") = 72
    dict("bar") = 72
 
    dict("baz") = 42
    dict("baz") = 42
+
    dict("hoge") = 3
+
    dict("huga") = 42
+

          
+
    ' 削除対象のキーを格納するList
+
    Dim removeKeys As New List(Of String)
 

        

        
 
    For Each pair As KeyValuePair(Of String, Integer) In dict
    For Each pair As KeyValuePair(Of String, Integer) In dict
~
      ' 値が42の場合は、削除対象としてListにキーを追加
      ' 値が42の場合は、削除する
~
      If pair.Value = 42 Then removeKeys.Add(pair.Key)
      If pair.Value = 42 Then dict.Remove(pair.Key)
+
    Next
+

          
+
    ' 対象となるキーを持つ要素を削除
+
    For Each key As String In removeKeys
+
      dict.Remove(key)
+
    Next
+

          
+
    ' 削除後のDictionaryの内容を列挙
+
    For Each pair As KeyValuePair(Of String, Integer) In dict
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value)
 
    Next
    Next
 
  End Sub
  End Sub
 
End Class
End Class
953,14 708,16
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
foo => 16
ハンドルされていない例外: System.InvalidOperationException: コレクションが変更されました。列挙操作は実行されない可能性があります。
~
bar => 72
   場所 System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
~
hoge => 3
   場所 Sample.Main()
 
}}
}}
 

        

        
~
また別の方法として、次の例のように別のDictionaryを用意し、元のDictionaryから条件に合う要素だけを別のDictionaryコピーすることで要素を削除した場合と同等のDictionaryを得るという方法もあります。
例外が発生する理由や回避する方法については[[programming/netfx/enumeration]]でも解説していますが、Dictionaryクラスには[[List.ForEachメソッド>programming/netfx/collections/2_generic_1_list#List_Enumeartion]]のような列挙操作を行うメソッドは用意されていないためこれを使った方法は適用できません。
 

        

        
~
#tabpage(codelang=cs,container-title=特定の要素だけを除外して新しいDictionaryを作成する例)
上記の例のように条件に合う要素を検索して削除するといった場合は、列挙による要素の検索と削除を別々のforeach文で行うようにすることでInvalidOperationExceptionの発生を回避することが出来ます。 また別の方法として、次の例のように別のDictionaryを用意して、元のDictionaryから条件に合う要素だけを別のDictionaryコピーするという方法もあります。
-

          
-
#tabpage(codelang=cs,container-title=列挙中の要素の削除)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
974,8 731,6
 
    dict["foo"] = 16;
    dict["foo"] = 16;
 
    dict["bar"] = 72;
    dict["bar"] = 72;
 
    dict["baz"] = 42;
    dict["baz"] = 42;
+
    dict["hoge"] = 3;
+
    dict["huga"] = 42;
 

        

        
 
    Dictionary<string, int> newdict = new Dictionary<string, int>();
    Dictionary<string, int> newdict = new Dictionary<string, int>();
 

        

        
1006,8 761,6
 
    dict("foo") = 16
    dict("foo") = 16
 
    dict("bar") = 72
    dict("bar") = 72
 
    dict("baz") = 42
    dict("baz") = 42
+
    dict("hoge") = 3;
+
    dict("huga") = 42;
 

        

        
 
    Dim newdict As New Dictionary(Of String, Integer)()
    Dim newdict As New Dictionary(Of String, Integer)()
 

        

        
1028,16 781,22
 
#prompt(実行結果){{
#prompt(実行結果){{
 
foo => 16
foo => 16
 
bar => 72
bar => 72
+
hoge => 3
 
}}
}}
 

        

        
+
特定要素を除外した列挙が行えればよいのであれば、LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.Where){Where};を使って次のようにすることもできます。
 

        

        
~
#tabpage(codelang=cs,container-title=Whereメソッドを使用して特定の要素だけを除外して要素を列挙する例)
**要素の並べ替え (ソート)
-
Dictionaryは順序を持たないことからDictionaryをソートされた状態にすることは出来ず、またそのようなメソッドも用意されていません。 ソートされた状態で内容を取得したい場合は、[[要素の列挙>#Dictionary_Enumeration]]に挙げたような方法で一旦Listに変換するか、値とキーをコピーしてからソートするなどの方法をとる必要があります。 Dictionaryとソートについてより詳しくは[[programming/netfx/sorting/0_basictypes#SortDictionary]]で解説しています。
-

          
-
また、常に要素を並べ替えた状態にしておきたい場合や格納される要素の順序が重要になる場合は、Dictionaryの代わりに[[SortedListやSortedDictionary>programming/netfx/collections/2_generic_3_sortedlist_sorteddictionary]]を使うことが出来ます。
-

          
-

          
-
**要素の検索 [#ContainsKeyContainsValue]
-
Dictionaryに指定したキーが存在するかどうかを調べるには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.ContainsKey){ContainsKeyメソッド};、値が存在するかどうかを調べるには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.ContainsValue){ContainsValueメソッド};を使います。
-

          
-
#tabpage(codelang=cs,container-title=要素の検索)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
+
using System.Linq;
 

        

        
 
class Sample
class Sample
 
{
{
1048,14 807,18
 
    dict["foo"] = 16;
    dict["foo"] = 16;
 
    dict["bar"] = 72;
    dict["bar"] = 72;
 
    dict["baz"] = 42;
    dict["baz"] = 42;
+
    dict["hoge"] = 3;
+
    dict["huga"] = 42;
 

        

        
~
    // 値が42以外の要素のみを列挙
    // キー"foo"を持つ要素があるかどうか
~
    foreach (KeyValuePair<string, int> pair in dict.Where(p => p.Value != 42))
    Console.WriteLine("ContainsKey(foo) = {0}", dict.ContainsKey("foo"));
~
    {

          
~
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value);
    // キー"hoge"を持つ要素があるかどうか
~
    }
    Console.WriteLine("ContainsKey(hoge) = {0}", dict.ContainsKey("hoge"));
-

          
-
    // 値16を持つ要素があるかどうか
-
    Console.WriteLine("ContainsValue(16) = {0}", dict.ContainsValue(16));
-

          
-
    // 値9を持つ要素があるかどうか
-
    Console.WriteLine("ContainsValue(9) = {0}", dict.ContainsValue(9));
 
  }
  }
 
}
}
 
}}
}}
1063,7 826,6
 
#code{{
#code{{
 
Imports System
Imports System
 
Imports System.Collections.Generic
Imports System.Collections.Generic
+
Imports System.Linq
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
1072,171 834,10
 
    dict("foo") = 16
    dict("foo") = 16
 
    dict("bar") = 72
    dict("bar") = 72
 
    dict("baz") = 42
    dict("baz") = 42
+
    dict("hoge") = 3
+
    dict("huga") = 42
+

          
+
    ' 値が42以外の要素のみを列挙
+
    For Each pair As KeyValuePair(Of String, Integer) In dict.Where(Function(p) p.Value <> 42)
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
foo => 16
+
bar => 72
+
hoge => 3
+
}}
+

          
+

          
+
**要素の並べ替え (ソート)
+
Dictionaryは順序を持たないことからDictionaryをソートされた状態にすることは出来ず、またそのようなメソッドも用意されていません。 Dictionary内の各ペアをソートされた状態にしたい場合は、次の例のように一旦Listに変換し、List.Sortメソッドを使って並べ替えを行う、といった方法をとる必要があります。
+

          
+
#tabpage(codelang=cs,container-title=DictionaryをListに変換してソートする例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // DictionaryをList<KeyValuePair>に変換
+
    List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(dict);
+

          
+
    // List.Sortメソッドでキーを使ってペアをソートする
+
    Console.WriteLine("[sort by key]");
+

          
+
    list.Sort((x, y) => string.Compare(x.Key, y.Key));
+

          
+
    foreach (KeyValuePair<string, int> pair in list)
+
    {
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value);
+
    }
+

          
+
    // List.Sortメソッドで値を使ってペアをソートする
+
    Console.WriteLine("[sort by value]");
+

          
+
    list.Sort((x, y) => x.Value - y.Value);
+

          
+
    foreach (KeyValuePair<string, int> pair in list)
+
    {
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' DictionaryをList(Of KeyValuePair)に変換
+
    Dim list As New List(Of KeyValuePair(Of String, Integer))(dict)
+

          
+
    ' List.Sortメソッドでキーを使ってペアをソートする
+
    Console.WriteLine("[sort by key]")
+

          
+
    list.Sort(Function(x, y) String.Compare(x.Key, y.Key))
+

          
+
    For Each pair As KeyValuePair(Of String, Integer) In list
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value)
+
    Next
+

          
+
    ' List.Sortメソッドで値を使ってペアをソートする
+
    Console.WriteLine("[sort by value]")
+

          
+
    list.Sort(Function(x, y) x.Value - y.Value)
+

          
+
    For Each pair As KeyValuePair(Of String, Integer) In list
+
      Console.WriteLine("{0} => {1}", pair.Key, pair.Value)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
[sort by key]
+
bar => 72
+
baz => 42
+
foo => 16
+
[sort by value]
+
foo => 16
+
baz => 42
+
bar => 72
+
}}
+

          
+
このほか、Dictionaryをソートする方法については[[programming/netfx/sorting/0_basictypes#SortDictionary]]で詳しく解説しています。
+

          
+
なお、要素を常に並べ替えた状態にしておきたい場合や、格納される要素の順序が重要になる場合は、Dictionaryの代わりに[[SortedListやSortedDictionary>programming/netfx/collections/2_generic_3_sortedlist_sorteddictionary]]を使うことも出来ます。
+

          
+

          
+
**要素の検索
+
***キー・値の有無チェック (ContainsKey, ContainsValue) [#ContainsKeyContainsValue]
+
Dictionaryに指定したキーが存在するかどうかを調べるには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.ContainsKey){ContainsKeyメソッド};、値が存在するかどうかを調べるには&msdn(netfx,member,System.Collections.Generic.Dictionary`2.ContainsValue){ContainsValueメソッド};を使います。
+

          
+
#tabpage(codelang=cs,container-title=要素の検索)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // キー"foo"を持つ要素があるかどうか
+
    Console.WriteLine("ContainsKey(foo) = {0}", dict.ContainsKey("foo"));
+

          
+
    // キー"hoge"を持つ要素があるかどうか
+
    Console.WriteLine("ContainsKey(hoge) = {0}", dict.ContainsKey("hoge"));
+

          
+
    // 値16を持つ要素があるかどうか
+
    Console.WriteLine("ContainsValue(16) = {0}", dict.ContainsValue(16));
+

          
+
    // 値9を持つ要素があるかどうか
+
    Console.WriteLine("ContainsValue(9) = {0}", dict.ContainsValue(9));
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' キー"foo"を持つ要素があるかどうか
+
    Console.WriteLine("ContainsKey(foo) = {0}", dict.ContainsKey("foo"))
 

        

        
-
    ' キー"foo"を持つ要素があるかどうか
-
    Console.WriteLine("ContainsKey(foo) = {0}", dict.ContainsKey("foo"))
-

          
 
    ' キー"hoge"を持つ要素があるかどうか
    ' キー"hoge"を持つ要素があるかどうか
 
    Console.WriteLine("ContainsKey(hoge) = {0}", dict.ContainsKey("hoge"))
    Console.WriteLine("ContainsKey(hoge) = {0}", dict.ContainsKey("hoge"))
 

        

        
1339,10 940,12
 
}}
}}
 

        

        
 

        

        
~
***値からキーの逆引き検索
*Dictionaryとキー [#Dictionary_EqualityComparer]
~
Dictionaryには値から対応するキーを逆引きするメソッドは用意されていません。 そのため、次の例のようにDictionaryの全要素を列挙して該当するKeyValuePairを検索するよう独自に実装する必要があります。

          
-
**キー比較のカスタマイズ
-
Hashtableと同様、コンストラクタで適切なIEqualityComparer<T>インターフェイスを指定することで、Dictionaryのキー比較時の動作をカスタマイズ出来ます。 例えば、文字列をキーとした場合に大文字小文字を無視するようにするといったことが出来ます。 以下は、StringComparerクラスを使って、大文字小文字を無視するDictionaryを作成する例です。
 

        

        
~
#tabpage(codelang=cs,container-title=値から対応するキーを逆引きする例)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
1351,35 954,36
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
~
    Dictionary<string, int> dict = new Dictionary<string, int>();
    // 大文字小文字の違いを無視しないDictionaryを作成
-
    // (キーの比較にStringComparer.CurrentCultureを使用)
-
    Dictionary<string, int> caseSensitiveDictionary = new Dictionary<string, int>(StringComparer.CurrentCulture);
-

          
-
    caseSensitiveDictionary["foo"] = 1;
-
    caseSensitiveDictionary["bar"] = 2;
-
    caseSensitiveDictionary["FOO"] = 3;
-
    caseSensitiveDictionary["BAR"] = 4;
-

          
-
    // 大文字小文字の違いを無視するDictionaryを作成
-
    // (キーの比較にStringComparer.CurrentCultureIgnoreCaseを使用)
-
    Dictionary<string, int> caseInsensitiveDictionary = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
 

        

        
~
    dict["foo"] = 16;
    caseInsensitiveDictionary["foo"] = 1;
~
    dict["bar"] = 72;
    caseInsensitiveDictionary["bar"] = 2;
~
    dict["baz"] = 42;
    caseInsensitiveDictionary["FOO"] = 3;
-
    caseInsensitiveDictionary["BAR"] = 4;
 

        

        
~
    // 値に42を持つ要素を検索する
    Console.WriteLine("caseSensitiveDictionary");
+
    int val = 42;
+
    bool found = false;
+
    KeyValuePair<string, int> match = new KeyValuePair<string, int>();
 

        

        
~
    foreach (KeyValuePair<string, int> pair in dict)
    foreach (KeyValuePair<string, int> entry in caseSensitiveDictionary)
 
    {
    {
~
      if (pair.Value == val)
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
+
      {
+
        // 該当する値を持つ要素が見つかった場合
+
        found = true;
+
        match = pair;
+
        break;
+
      }
 
    }
    }
 

        

        
~
    if (found)
    Console.WriteLine("caseInsensitiveDictionary");
-

          
-
    foreach (KeyValuePair<string, int> entry in caseInsensitiveDictionary)
 
    {
    {
~
      Console.WriteLine("値{0}を持つ要素のキーは'{1}'です", match.Value, match.Key);
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
+
    }
+
    else
+
    {
+
      Console.WriteLine("値{0}を持つ要素は見つかりませんでした", val);
 
    }
    }
 
  }
  }
 
}
}
1391,620 995,53
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    Dim dict As New Dictionary(Of String, Integer)()
    ' 大文字小文字の違いを無視しないDictionaryを作成
-
    ' (キーの比較にStringComparer.CurrentCultureを使用)
-
    Dim caseSensitiveDictionary As New Dictionary(Of String, Integer)(StringComparer.CurrentCulture)
 

        

        
~
    dict("foo") = 16
    caseSensitiveDictionary("foo") = 1
~
    dict("bar") = 72
    caseSensitiveDictionary("bar") = 2
~
    dict("baz") = 42
    caseSensitiveDictionary("FOO") = 3
-
    caseSensitiveDictionary("BAR") = 4
 

        

        
~
    ' 値に42を持つ要素を検索する
    ' 大文字小文字の違いを無視するDictionaryを作成
~
    Dim val As Integer = 42
    ' (キーの比較にStringComparer.CurrentCultureIgnoreCaseを使用)
~
    Dim found As Boolean = False
    Dim caseInsensitiveDictionary As New Dictionary(Of String, Integer)(StringComparer.CurrentCultureIgnoreCase)
+
    Dim match As New KeyValuePair(Of String, Integer)()
 

        

        
~
    For Each pair As KeyValuePair(Of String, Integer) In dict
    caseInsensitiveDictionary("foo") = 1
~
      If pair.Value = val Then
    caseInsensitiveDictionary("bar") = 2
~
        ' 該当する値を持つ要素が見つかった場合
    caseInsensitiveDictionary("FOO") = 3
~
        found = True
    caseInsensitiveDictionary("BAR") = 4
+
        match = pair
+
        Exit For
+
      End If
+
    Next
 

        

        
~
    If found Then
    Console.WriteLine("caseSensitiveDictionary")
+
      Console.WriteLine("値{0}を持つ要素のキーは'{1}'です", match.Value, match.Key)
+
    Else
+
      Console.WriteLine("値{0}を持つ要素は見つかりませんでした", val)
+
    End If
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
    For Each entry As KeyValuePair(Of String, Integer) In caseSensitiveDictionary
~
値42を持つ要素のキーは'baz'です
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
~
}}
    Next
 

        

        
~
LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.First){First};を使って逆引きする場合は次のように記述できます。
    Console.WriteLine("caseInsensitiveDictionary")
 

        

        
~
#tabpage(codelang=cs,container-title=Firstメソッドを使って値から対応するキーを逆引きする例)
    For Each entry As KeyValuePair(Of String, Integer) In caseInsensitiveDictionary
~
#code{{
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
~
using System;
    Next
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // 値に42を持つ要素を検索する
+
    int val = 42;
+

          
+
    try {
+
      KeyValuePair<string, int> match = dict.First(pair => pair.Value == val);
+

          
+
      Console.WriteLine("値{0}を持つ要素のキーは'{1}'です", match.Value, match.Key);
+
    }
+
    catch (InvalidOperationException) {
+
      Console.WriteLine("値{0}を持つ要素は見つかりませんでした", val);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' 値に42を持つ要素を検索する
+
    Dim val As Integer = 42
+

          
+
    Try
+
      Dim match As KeyValuePair(Of String, Integer) = dict.First(Function(pair) pair.Value = val)
+

          
+
      Console.WriteLine("値{0}を持つ要素のキーは'{1}'です", match.Value, match.Key)
+
    Catch ex As InvalidOperationException
+
      Console.WriteLine("値{0}を持つ要素は見つかりませんでした", val)
+
    End Try
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
~
値42を持つ要素のキーは'baz'です
caseSensitiveDictionary
~
}}
foo => 1
~

          
bar => 2
~

          
FOO => 3
~
**最初の要素・最後の要素
BAR => 4
~
[[#ordered_enumeration]]でも述べたようにDictionaryに格納される要素には順序の概念が無いため、最初の要素・最後の要素は定義することができず、そういった要素を取得するプロパティ等も提供されません。
caseInsensitiveDictionary
~

          
foo => 3
~
LINQの拡張メソッド&msdn(netfx,member,System.Linq.Enumerable.OrderBy){OrderBy};で並べ替えを行い、その中から最初の要素・最後の要素を取得したい場合には同じく拡張メソッドの&msdn(netfx,member,System.Linq.Enumerable.First){Firstメソッド};・&msdn(netfx,member,System.Linq.Enumerable.Last){Lastメソッド};を使うことができます。
bar => 4
+

          
+
#tabpage(codelang=cs,container-title=Firstメソッド・Lastメソッドを使って最初・最後に列挙される要素を取得する例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // キーで並べ替えた場合に最初に位置する要素を取得する
+
    KeyValuePair<string, int> first = dict.OrderBy(pair => pair.Key).First();
+

          
+
    Console.WriteLine("first of order by key: {0} => {1}", first.Key, first.Value);
+

          
+
    // キーで並べ替えた状態で最後に列挙される要素を取得する
+
    KeyValuePair<string, int> last = dict.OrderBy(pair => pair.Key).Last();
+

          
+
    Console.WriteLine("last of order by key: {0} => {1}", last.Key, last.Value);
+

          
+
    // 値で並べ替えた場合に最初に位置する要素を取得する
+
    first = dict.OrderBy(pair => pair.Value).First();
+

          
+
    Console.WriteLine("first of order by value: {0} => {1}", first.Key, first.Value);
+

          
+
    // 値で並べ替えた場合に最後に位置する要素を取得する
+
    last = dict.OrderBy(pair => pair.Value).Last();
+

          
+
    Console.WriteLine("last of order by value: {0} => {1}", last.Key, last.Value);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' キーで並べ替えた場合に最初に位置する要素を取得する
+
    Dim first As KeyValuePair(Of String, Integer) = dict.OrderBy(Function(pair) pair.Key).First()
+

          
+
    Console.WriteLine("first of order by key: {0} => {1}", first.Key, first.Value)
+

          
+
    ' キーで並べ替えた状態で最後に列挙される要素を取得する
+
    Dim last As KeyValuePair(Of String, Integer) = dict.OrderBy(Function(pair)  pair.Key).Last()
+

          
+
    Console.WriteLine("last of order by key: {0} => {1}", last.Key, last.Value)
+

          
+
    ' 値で並べ替えた場合に最初に位置する要素を取得する
+
    first = dict.OrderBy(Function(pair) pair.Value).First()
+

          
+
    Console.WriteLine("first of order by value: {0} => {1}", first.Key, first.Value)
+

          
+
    ' 値で並べ替えた場合に最後に位置する要素を取得する
+
    last = dict.OrderBy(Function(pair) pair.Value).Last()
+

          
+
    Console.WriteLine("last of order by value: {0} => {1}", last.Key, last.Value)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
first of order by key: bar => 72
+
last of order by key: foo => 16
+
first of order by value: foo => 16
+
last of order by value: bar => 72
+
}}
+

          
+

          
+
*Dictionaryとキー [#Dictionary_EqualityComparer]
+

          
+
**キー比較のカスタマイズ
+
Hashtableと同様、コンストラクタで適切なIEqualityComparer<T>インターフェイスを指定することで、Dictionaryのキー比較時の動作をカスタマイズ出来ます。 例えば、文字列をキーとした場合に大文字小文字を無視するようにするといったことが出来ます。 以下は、StringComparerクラスを使って、大文字小文字を無視するDictionaryを作成する例です。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 大文字小文字の違いを無視しないDictionaryを作成
+
    // (キーの比較にStringComparer.CurrentCultureを使用)
+
    Dictionary<string, int> caseSensitiveDictionary = new Dictionary<string, int>(StringComparer.CurrentCulture);
+

          
+
    caseSensitiveDictionary["foo"] = 1;
+
    caseSensitiveDictionary["bar"] = 2;
+
    caseSensitiveDictionary["FOO"] = 3;
+
    caseSensitiveDictionary["BAR"] = 4;
+

          
+
    // 大文字小文字の違いを無視するDictionaryを作成
+
    // (キーの比較にStringComparer.CurrentCultureIgnoreCaseを使用)
+
    Dictionary<string, int> caseInsensitiveDictionary = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
+

          
+
    caseInsensitiveDictionary["foo"] = 1;
+
    caseInsensitiveDictionary["bar"] = 2;
+
    caseInsensitiveDictionary["FOO"] = 3;
+
    caseInsensitiveDictionary["BAR"] = 4;
+

          
+
    Console.WriteLine("caseSensitiveDictionary");
+

          
+
    foreach (KeyValuePair<string, int> entry in caseSensitiveDictionary)
+
    {
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
+
    }
+

          
+
    Console.WriteLine("caseInsensitiveDictionary");
+

          
+
    foreach (KeyValuePair<string, int> entry in caseInsensitiveDictionary)
+
    {
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 大文字小文字の違いを無視しないDictionaryを作成
+
    ' (キーの比較にStringComparer.CurrentCultureを使用)
+
    Dim caseSensitiveDictionary As New Dictionary(Of String, Integer)(StringComparer.CurrentCulture)
+

          
+
    caseSensitiveDictionary("foo") = 1
+
    caseSensitiveDictionary("bar") = 2
+
    caseSensitiveDictionary("FOO") = 3
+
    caseSensitiveDictionary("BAR") = 4
+

          
+
    ' 大文字小文字の違いを無視するDictionaryを作成
+
    ' (キーの比較にStringComparer.CurrentCultureIgnoreCaseを使用)
+
    Dim caseInsensitiveDictionary As New Dictionary(Of String, Integer)(StringComparer.CurrentCultureIgnoreCase)
+

          
+
    caseInsensitiveDictionary("foo") = 1
+
    caseInsensitiveDictionary("bar") = 2
+
    caseInsensitiveDictionary("FOO") = 3
+
    caseInsensitiveDictionary("BAR") = 4
+

          
+
    Console.WriteLine("caseSensitiveDictionary")
+

          
+
    For Each entry As KeyValuePair(Of String, Integer) In caseSensitiveDictionary
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
+
    Next
+

          
+
    Console.WriteLine("caseInsensitiveDictionary")
+

          
+
    For Each entry As KeyValuePair(Of String, Integer) In caseInsensitiveDictionary
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
caseSensitiveDictionary
+
foo => 1
+
bar => 2
+
FOO => 3
+
BAR => 4
+
caseInsensitiveDictionary
+
foo => 3
+
bar => 4
+
}}
+

          
+
**キーと複合型
+
Dictionaryクラスでは、キーとなる型が&msdn(netfx,member,System.Object.Equals){Equalsメソッド};と&msdn(netfx,member,System.Object.GetHashCode){GetHashCodeメソッド};をオーバーライドしていて、かつ適切な値を返すように実装されていないと正しく動作しません。 キーに独自に定義した型を指定してDictionaryを使用したい場合は、これらのメソッドをオーバーライドして適切に実装するか、Dictionaryのコンストラクタに&msdn(netfx,type,System.Collections.Generic.IEqualityComparer`1){IEqualityComparer<T>インターフェイス};を指定する必要があります。 IEqualityComparer<T>インターフェイスの実装方法や、独自に定義した型をキーにする例については[[programming/netfx/comparison/1_equation]]で解説しています。
+

          
+

          
+

          
+
*Dictionaryとインデックス
+
Dictionaryでは格納される要素はキーによってのみ管理されます。 また''順序を持たないコレクション''であるためインデックスという概念を持たず、インデックスを指定したキー・値の参照・設定などの操作も提供されません。 これに従って、for文による列挙も行えません。 当然、IndexOfKey・IndexOfValueといったキー・値のインデックスを取得するような操作も提供されません。
+

          
+
**インデックスを指定した操作
+
インデックスを使った操作を行いたい場合は、次の例のように一旦DictionaryからListに変換する、といった方法を取る必要があります。
+

          
+
#tabpage(codelang=cs,container-title=DictionaryからListに変換して列挙する)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // Dictionaryと同じ内容を含むListを作成
+
    List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(dict);
+

          
+
    // for文を使って作成したListを列挙
+
    for (int i = 0; i < list.Count; i++)
+
    {
+
      Console.WriteLine("{0} : {1} => {2}", i, list[i].Key, list[i].Value);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' Dictionaryと同じ内容を含むListを作成
+
    Dim list As New List(Of KeyValuePair(Of String, Integer))(dict)
+

          
+
    ' Forステートメントを使って作成したListを列挙
+
    For i As Integer = 0 To list.Count - 1
+
      Console.WriteLine("{0} : {1} => {2}", i, list(i).Key, list(i).Value)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0 : foo => 16
+
1 : bar => 72
+
2 : baz => 42
+
}}
+

          
+
キーもしくは値を配列にコピーしてから列挙したい場合は、次の例のようにKeysプロパティ・Valuesプロパティを参照してCopyToメソッドによって配列にコピーした上で列挙するという方法がとれます。
+

          
+
#tabpage(codelang=cs,container-title=Dictionaryのすべてのキーと値を配列にコピーして列挙する)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Dictionary<string, int> dict = new Dictionary<string, int>();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // キーと値を格納するための配列を作成
+
    string[] keys = new string[dict.Count];
+
    int[] values = new int[dict.Count];
+

          
+
    // キーと値を配列にコピー
+
    dict.Keys.CopyTo(keys, 0);
+
    dict.Values.CopyTo(values, 0);
+

          
+
    // for文を使ってコピーしたキーと値の配列を列挙
+
    for (int i = 0; i < keys.Length; i++)
+
    {
+
      Console.WriteLine("{0} : {1} => {2}", i, keys[i], values[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New Dictionary(Of String, Integer)()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' キーと値を格納するための配列を作成
+
    Dim keys(dict.Count - 1) As String
+
    Dim values(dict.Count - 1) As Integer
+

          
+
    ' キーと値を配列にコピー
+
    dict.Keys.CopyTo(keys, 0)
+
    dict.Values.CopyTo(values, 0)
+

          
+
    ' Forステートメントを使ってコピーしたキーと値の配列を列挙
+
    For i As Integer = 0 To keys.Length - 1
+
      Console.WriteLine("{0} : {1} => {2}", i, keys(i), values(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0 : foo => 16
+
1 : bar => 72
+
2 : baz => 42
+
}}
+

          
+
キーの型をintなどの整数型にすることでインデックスを持たせたDictionaryのように扱うことはできますが、[[#ordered_enumeration]]でも述べたようにDictionaryに格納された要素をforeach文で列挙する際の順序は不定である点、インデックス(キー)が不連続な値となりうる点などから、あまり推奨できる方法ではありません。
+

          
+
#tabpage(codelang=cs,container-title=Dictionaryのキーをインデックスとして扱う例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // キーをintにしてインデックスとして扱う
+
    Dictionary<int, string> dict = new Dictionary<int, string>();
+

          
+
    dict[0] = "foo";
+
    dict[1] = "bar";
+
    dict[3] = "baz";
+

          
+
    for (int i = 0; i < dict.Count; i++)
+
    {
+
      // キー2の要素は存在しないため、途中で例外が発生する
+
      Console.WriteLine("{0} => {1}", i, dict[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' キーをIntegerにしてインデックスとして扱う
+
    Dim dict As New Dictionary(Of Integer, String)()
+

          
+
    dict(0) = "foo"
+
    dict(1) = "bar"
+
    dict(3) = "baz"
+

          
+
    For i As Integer = 0 To dict.Count - 1
+
      ' キー2の要素は存在しないため、途中で例外が発生する
+
      Console.WriteLine("{0} => {1}", i, dict(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0 => foo
+
1 => bar
+

          
+
ハンドルされていない例外: System.Collections.Generic.KeyNotFoundException: 指定されたキーはディレクトリ内に存在しませんでした。
+
   場所 System.Collections.Generic.Dictionary`2.get_Item(TKey key)
+
   場所 Sample.Main()
+
}}
+

          
+
**SortedList
+
[[SortedList>programming/netfx/collections/2_generic_3_sortedlist_sorteddictionary]]を使うと、キーと値のペアにインデックスを持たせることができます。 ただし、SortedListではインデックスを指定して要素を格納することはできません。 常にキーで要素を並べ替えた時の順序でインデックスが割り振られます。
+

          
+
#tabpage(codelang=cs,container-title=DictionaryのかわりにSortedListを使う例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    SortedList<string, int> list = new SortedList<string, int>();
+

          
+
    list["foo"] = 16;
+
    list["bar"] = 72;
+
    list["baz"] = 42;
+

          
+
    Console.WriteLine("IndexOfKey(foo) = {0}", list.IndexOfKey("foo"));
+
    Console.WriteLine("IndexOfValue(42) = {0}", list.IndexOfValue(42));
+

          
+
    for (int i = 0; i < list.Count; i++)
+
    {
+
      Console.WriteLine("{0}: {1} => {2}", i, list.Keys[i], list.Values[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim list As New SortedList(Of String, Integer)()
+

          
+
    list("foo") = 16
+
    list("bar") = 72
+
    list("baz") = 42
+

          
+
    Console.WriteLine("IndexOfKey(foo) = {0}", list.IndexOfKey("foo"))
+
    Console.WriteLine("IndexOfValue(42) = {0}", list.IndexOfValue(42))
+

          
+
    For i As Integer = 0 To list.Count - 1
+
      Console.WriteLine("{0}: {1} => {2}", i, list.Keys(i), list.Values(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
IndexOfKey(foo) = 2
+
IndexOfValue(42) = 1
+
0: bar => 72
+
1: baz => 42
+
2: foo => 16
+
}}
+

          
+
**OrderedDictionary
+
System.Collections.Specialized名前空間の&msdn(netfx,type,System.Collections.Specialized.OrderedDictionary){OrderedDictionaryクラス};では、要素が格納された順にインデックスが割り振られ、列挙する際も常に格納された順で列挙されます。 ただし、OrderedDictionaryは非ジェネリックなコレクションです。 OrderedDictionaryに相当するジェネリックコレクションは用意されていません。
+

          
+
#tabpage(codelang=cs,container-title=DictionaryのかわりにOrderedDictionaryを使う例)
+
#code{{
+
using System;
+
using System.Collections;
+
using System.Collections.Specialized;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    OrderedDictionary dict = new OrderedDictionary();
+

          
+
    dict["foo"] = 16;
+
    dict["bar"] = 72;
+
    dict["baz"] = 42;
+

          
+
    // OrderedDictionaryに格納された要素を列挙
+
    foreach (DictionaryEntry entry in dict)
+
    {
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value);
+
    }
+

          
+
    // OrderedDictionaryに格納されている値をインデックス順で列挙
+
    for (int i = 0; i < dict.Count; i++)
+
    {
+
      Console.WriteLine("{0}: {1}", i, dict[i]);
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections
+
Imports System.Collections.Specialized
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim dict As New OrderedDictionary()
+

          
+
    dict("foo") = 16
+
    dict("bar") = 72
+
    dict("baz") = 42
+

          
+
    ' OrderedDictionaryに格納された要素を列挙
+
    For Each entry As DictionaryEntry In dict
+
      Console.WriteLine("{0} => {1}", entry.Key, entry.Value)
+
    Next
+

          
+
    ' OrderedDictionaryに格納されている値をインデックス順で列挙
+
    For i As Integer = 0 To dict.Count - 1
+
      Console.WriteLine("{0}: {1}", i, dict(i))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
foo => 16
+
bar => 72
+
baz => 42
+
0: 16
+
1: 72
+
2: 42
 
}}
}}
 

        

        
-
**キーと複合型
-
Dictionaryクラスでは、キーとなる型が&msdn(netfx,member,System.Object.Equals){Equalsメソッド};と&msdn(netfx,member,System.Object.GetHashCode){GetHashCodeメソッド};をオーバーライドしていて、かつ適切な値を返すように実装されていないと正しく動作しません。 キーに独自に定義した型を指定してDictionaryを使用したい場合は、これらのメソッドをオーバーライドして適切に実装するか、Dictionaryのコンストラクタに&msdn(netfx,type,System.Collections.Generic.IEqualityComparer`1){IEqualityComparer<T>インターフェイス};を指定する必要があります。 IEqualityComparer<T>インターフェイスの実装方法や、独自に定義した型をキーにする例については[[programming/netfx/comparison/1_equation]]で解説しています。
 

        

        
 
*入れ子
*入れ子
 
Listや他のジェネリックコレクション同様、Dictionaryもキー・値ともに任意の型に型付けすることができるため、キー・値に他のジェネリックコレクション型を格納するようにすることも出来ます。 次の例では、Dictionaryクラスを使って文字列の辞書を処理するために入れ子になったDictionary<char, List<string>>を作成し、要素の追加・削除・列挙などの操作を行っています。
Listや他のジェネリックコレクション同様、Dictionaryもキー・値ともに任意の型に型付けすることができるため、キー・値に他のジェネリックコレクション型を格納するようにすることも出来ます。 次の例では、Dictionaryクラスを使って文字列の辞書を処理するために入れ子になったDictionary<char, List<string>>を作成し、要素の追加・削除・列挙などの操作を行っています。
2197,7 1234,7
 

        

        
 

        

        
 
*読み取り専用 [#Dictionary_ReadOnly]
*読み取り専用 [#Dictionary_ReadOnly]
~
Dictionaryには[[List.AsReadOnlyメソッド>programming/netfx/collections/2_generic_1_list#List.AsReadOnly]]のようなメソッドが存在しないため、読み取り専用のDictionaryを作成する手段が存在しません。 .NET Framework 4.5からは&msdn(netfx,type,System.Collections.ObjectModel.ReadOnlyDictionary`2){ReadOnlyDictionary};が導入されましたが、それ以前のバージョンでは使用することができないため、読み取り専用のDictionaryが必要な場合は自前で実装する必要があります。
Dictionaryには[[List.AsReadOnlyメソッド>programming/netfx/collections/2_generic_1_list#List.AsReadOnly]]のようなメソッドが存在しないため、読み取り専用のDictionaryを作成する手段が存在しません。 また、[[ReadOnlyCollection>programming/netfx/collections/3_objectmodel_1_collection#ReadOnlyCollection]]に相当するようなクラスも存在していないため読み取り専用のDictionaryが必要な場合は、自前で実装する必要があります。
 

        

        
 
次の例はそのような読み取り専用のクラスReadOnlyDictionaryを実装した例です。 動作やスローする例外等は[[ReadOnlyCollection>programming/netfx/collections/3_objectmodel_1_collection#ReadOnlyCollection]]に近いものとなるようにしています。 また、IDictionaryに対して拡張メソッドAsReadOnlyを追加するためのクラスIDictionaryExtensionsも作成しています。 なお、この例で実装しているReadOnlyDictionaryクラスでは元のDictionaryを読み取り専用にする訳ではないので注意してください。 元になったDictionaryは、依然として要素の追加・削除・変更が可能です。
次の例はそのような読み取り専用のクラスReadOnlyDictionaryを実装した例です。 動作やスローする例外等は[[ReadOnlyCollection>programming/netfx/collections/3_objectmodel_1_collection#ReadOnlyCollection]]に近いものとなるようにしています。 また、IDictionaryに対して拡張メソッドAsReadOnlyを追加するためのクラスIDictionaryExtensionsも作成しています。 なお、この例で実装しているReadOnlyDictionaryクラスでは元のDictionaryを読み取り専用にする訳ではないので注意してください。 元になったDictionaryは、依然として要素の追加・削除・変更が可能です。