【C#】Dictionary (ディクショナリ)

■ 使用上の注意

★重要★ Dictionary へのデータ追加について

 * dict.Add() と dict[] だと、キーが重複してた際に以下のような違いがある
~~~~~
 [1] dict.Add() の場合、例外が発生(以下「※例外内容」を参照)
 [2] dict[]の場合、上書き
※例外内容
System.ArgumentException : 同一のキーを含む項目が既に追加されています
追記:ToDictionary()の動作について
 * 以下のサイトによると、ToDictionary()でも例外が発生するらしい
https://qiita.com/YSRKEN/items/b4bad929fe49e38faa26

■ Dictionaryをマージする

 * Linq / Concat / ToDictionary を使う
~~~~
var dictResults = dictNew.Concat(
  dictOld.Where(pair =>!dictNew.ContainsKey(pair.Key)))
  .ToDictionary(pair => pair.Key, i => pair.Value);
~~~~

サンプル

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace SampleForm
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      var dictOld = new Dictionary<string, int> { { "Key11", 101 }, { "Key12", 102 }, { "Key13", 103 } };
      var dictNew = new Dictionary<string, int> { { "Key21", 201 }, { "Key12", 202 }, { "Key13", 203 }, { "Key24", 204 } };

      var dictResults = dictNew.Concat(
        dictOld.Where(pair =>!dictNew.ContainsKey(pair.Key)))
        .ToDictionary(pair => pair.Key, i => pair.Value);
      foreach (var result in dictResults)
      {
        this.label1.Text = this.label1.Text + $"{result.Key} {result.Value}" + "\n";
      }
    }
  }
}
出力結果
Key21 201
Key12 202
Key13 203
Key24 204
Key11 101

参考文献

https://qiita.com/Nossa/items/802b0e0de927c0cfec05

■ DictionaryをValueからKeyを逆引きする

 * Linqを使う

サンプル

using System.Linq;

private void button10_Click(object sender, EventArgs e)
{
Dictionary<string, string> dictionaries = new Dictionary<string, string>()
{
{"appliance", "機器"},
{"proceed", "売り上げ"},
{"state-of-the-art", "最新の"},
{"recognize", "認める"},
{"production", "製品"},
};

this.label1.Text = this.GetKeyByValue(dictionaries, "最新の");
}

private string GetKeyByValue(Dictionary<string, string> dictionaries, string value)
{
return dictionaries.FirstOrDefault(x => x.Value == value).Key;
}

■ Dictionary版TryParse

 * Dictionary.TryGetValue()を使う

■ DictinaryのKeyを、リストとして取得する

 * 「IList<string> list = dictionaries.Select(c => c.Key).ToList();」で可能

サンプル

private void button1_Click(object sender, EventArgs e)
{
    Dictionary<string, string> dictionaries
        = new Dictionary<string, string>()
        {
            {"appliance", "機器"},
            {"proceed", "売り上げ"},
            {"state-of-the-art", "最新の"},
            {"recognize", "認める"},
            {"production", "製品"},
        };

    var list = dictionaries.Select(c => c.Key).ToList();

    string result = string.Empty;
    foreach (var stringData in list)
    {
        result = result + "\n" + stringData;
    }

    this.label1.Text = result;
}

■ DictinaryにTypeを登録する

 * Dictinaryには、クラスなども登録できるので便利
 * Type、typeof()、GetType()などについては、以下を参照
http://blogs.yahoo.co.jp/dk521123/19117857.html

サンプル

Dictionary<Type, string> dictionaries = new Dictionary<Type, string>
{
{typeof(Form), "フォーム"},
{typeof(Button), "ボタン"},
{typeof(Label), "ラベル"},
};

this.label1.Text = dictionaries[this.button1.GetType()];

■ DictinaryにDictinaryを設定

 * Dictinary内にDictinaryを設定できる

サンプル

 * Dictinary/Dictinary(この例ではaddressBooks)にデータがなかったら、
   住所データをDictinary/Dictinaryにデータ追加
Form1.cs (メインプログラム)
public partial class Form1 : Form
{
    public readonly Dictionary<NameOfUniversity, Dictionary<Department, string>>  addressBooks;

    public Form1()
    {
        InitializeComponent();

        // http://blogs.yahoo.co.jp/dk521123/20513549.html を参照
        this.comboBox1.DataSource = Enum.GetValues(typeof(NameOfUniversity));
        this.comboBox2.DataSource = Enum.GetValues(typeof(Department));

        addressBooks =
            new Dictionary<NameOfUniversity, Dictionary<Department, string>>
            {
                { NameOfUniversity.Tokyo, new Dictionary<Department, string>
                    {
                        { Department.Literature, "東京都XX区XX-X" },
                        { Department.Science, "東京都XX区YY-X" },
                    }
                },
                { NameOfUniversity.KO, new Dictionary<Department, string>
                    {
                        { Department.Literature, "東京都ZX区XY-Z" },
                    }
                },
            };
    }

    private void button7_Click(object sender, EventArgs e)
    {
        var name = (NameOfUniversity)this.comboBox1.SelectedValue;
        var department = (Department)this.comboBox2.SelectedValue;

        if (addressBooks.ContainsKey(name) && addressBooks[name].ContainsKey(department))
        {
            // addressBooks内の住所データをラベルに表示
            this.label1.Text = addressBooks[name][department];
        }
        else
        {
            DialogResult result =
                    MessageBox.Show(
                    this,
                    "単語帳に単語が見つかりませんでした。\n新規に単語を登録しますか?",
                    "Not Found",
                    MessageBoxButtons.YesNoCancel,
                    MessageBoxIcon.Question);
            if (result != DialogResult.Yes)
            {
                return;
            }

            // addressBooks内の住所データを登録
            if (addressBooks.ContainsKey(name))
            {
                // addressBooks内に存在する大学名の住所データを登録
                addressBooks[name][department] = this.textBox1.Text;
            }
            else
            {
                // addressBooks内に存在しない大学名の住所データを登録
                addressBooks.Add(name,
                    new Dictionary<Department, string>
                    {
                        { department, this.textBox1.Text },
                    });
            }
        }
    }
}
NameOfUniversity.cs (使用しているEnum [1])
public enum NameOfUniversity
{
    None,
    Tokyo,
    Waseda,
    KO,
}
Department.cs (使用しているEnum [2])
public enum Department
{
    None,
    Literature,
    Science,
    Medical,
}

関連記事

C# / コレクション

List (リスト)
https://blogs.yahoo.co.jp/dk521123/22295813.html
Concurrentコレクション ~ スレッドセーフなコレクション ~
https://blogs.yahoo.co.jp/dk521123/38017014.html
BlockingCollection ~ Producer-Consumerパターン ~
https://blogs.yahoo.co.jp/dk521123/37943991.html

その他

VBC#との差異 (ジェネリック、List、Dictionary 編)
https://blogs.yahoo.co.jp/dk521123/28112686.html