C#でプログラムを書いていて、ある日突然、
「同一のキーを含む項目が既に追加されています。」
というエラーが表示されてびっくりしたことはありませんか?
私もはじめてこのエラーに出くわしたとき、「えっ、何のこと?」と固まってしまった記憶があります。
エラーメッセージには「キーが重複していますよ」と書かれているのですが、コードをパッと見ただけでは原因がわからないことがほとんどです。
特に Dictionary
や ToDictionary()
を使っているときに、このエラーが急に出てきて、「さっきまで動いてたのに、なんで?」となりがちです。
本記事では、このエラーがなぜ起こるのか、どうすれば回避できるのかを、初心者の方にもわかりやすく、図やサンプルコードを交えながら丁寧に解説していきます。
「C#の辞書って便利だけど、落とし穴もあるんだな」と思ってもらえるような内容にしていますので、ぜひ最後までお付き合いください。
エラーの全文と発生タイミング
このエラーが発生したとき、Visual Studioの出力ウィンドウや例外の詳細には、こんなメッセージが表示されます。
System.ArgumentException: 同一のキーを含む項目が既に追加されています。
エラーメッセージを読んで「え、キーって何?」「どこで追加してるの?」と戸惑った方も多いと思います。
このエラーがよく起こるのは、Dictionary<TKey, TValue>
型に、すでに存在しているキーをもう一度追加しようとしたときです。Dictionary
については、こちらの記事で詳しく解説をしています。
たとえば、次のようなコードです。
var dict = new Dictionary<int, string>();
dict.Add(1, "りんご");
dict.Add(1, "バナナ"); // ← ここでエラーが発生!
このように、同じキー(この例では「1」)を2回 Add
しようとすると、C#は「いやいや、それもう入ってるよ」と怒ってしまうわけですね。
また、意外と見落としがちなのが LINQの ToDictionary()
メソッドを使ったときです。
一見シンプルに見えるコードでも、裏側で同じキーが複数あると、やはり同じエラーになります。
var fruits = new[] { "Apple", "Avocado", "Banana" };
var dict = fruits.ToDictionary(f => f[0]); // 'A' が2つ → エラー
このように、一見きれいに書けているつもりでも、データの中に「重複キー」が混ざっていると落とし穴になります。
このあとは、なぜこのようなエラーが起こるのかを、もう少し深掘りしていきましょう。
原因を解説

さて、前の章で「同じキーを2回追加しようとするとエラーになる」とお伝えしましたが、もう少しだけ詳しく、なぜこのエラーが発生するのかを見ていきましょう。
Dictionaryの「キー」は一意でなければならない
C#の Dictionary<TKey, TValue>
は、「キーと値のセット」を保持するコレクションです。
たとえば「社員ID → 社員名」とか「商品コード → 商品名」といった、「一意な情報」を使って値にアクセスするようなケースでよく使われます。
ここで重要なのが、「キー(TKey)」は重複してはいけないというルールです。
var dict = new Dictionary<string, string>();
dict.Add("A001", "コーヒー");
dict.Add("A001", "紅茶"); // ← 同じキー「A001」だからエラー!
このように、すでに「A001」というキーが登録されているのに、もう一度同じキーで追加しようとすると、「それ、もう登録済みです!」とC#が止めてくれるわけです。
LINQのToDictionaryも落とし穴になりやすい
もうひとつ、よくあるのが ToDictionary()
を使ったときです。
var fruits = new[] { "Apple", "Avocado", "Banana" };
var dict = fruits.ToDictionary(f => f[0]); // エラー発生!
上のコードでは、「単語の最初の1文字(f[0])」をキーにして辞書を作ろうとしています。
でも "Apple"
と "Avocado"
はどちらも 'A'
で始まるので、キーが重複してしまい、このときも例外がスローされます。
このように、データ自体に重複があるときや、キーを抽出するロジックが適切でないときも、同じエラーが発生します。
よくあるパターンと再現コード
「同一のキーを含む項目が既に追加されています。」というエラーは、主に以下のような場面でよく発生します。
パターン1:Dictionary.Addで同じキーを2回追加してしまう
var dict = new Dictionary<int, string>();
dict.Add(1, "りんご");
dict.Add(1, "バナナ"); // ← ここで例外が発生!
このパターンはとても基本的で、たとえばループや複数の処理の中で Add
を呼び出していると、気づかないうちに同じキーを2回追加してしまうことがあります。
パターン2:LINQのToDictionaryで、重複キーのデータを変換してしまう
var fruits = new[] { "Apple", "Avocado", "Banana" };
var dict = fruits.ToDictionary(f => f[0]); // ← 'A' が重複してエラー!
このコードでは、各単語の最初の文字をキーにしようとしていますが、「Apple」と「Avocado」はどちらも 'A'
で始まるため、重複キーになってしまいます。
LINQの ToDictionary
は、キーが重複すると容赦なく例外を投げてくるので注意が必要です。
パターン3:データソース側に重複があるのに気づかない
たとえばCSVやデータベースから読み込んだデータに、同じキーが複数含まれているケースです。
var employees = new[]
{
new { Id = 1, Name = "田中" },
new { Id = 1, Name = "鈴木" }, // ← Id が重複している!
new { Id = 2, Name = "佐藤" }
};
var dict = employees.ToDictionary(e => e.Id); // ← ここでエラー!
外部データは「重複しないだろう」と思い込んでしまいがちですが、現実には結構あるパターンです。このように、想定外の重複が原因で例外が発生することもよくあります。
解決策まとめ

ここまでで原因が分かったところで、気になるのは「じゃあどうすればエラーを防げるの?」という点ですよね。C#で「同一のキーを含む項目が既に追加されています」というエラーを回避・解決するための方法を、よく使われるケース別に紹介します。
方法1:Add()の代わりにインデクサ([])を使って上書き
dict[key] = value;
この方法なら、同じキーがすでに存在していても上書きされるだけで、例外は発生しません。
ただし、「前に入っていた値が上書きされる」点には注意しましょう。履歴が必要な場合には不向きです。
方法2:ContainsKey()で事前にキーの存在をチェック
if (!dict.ContainsKey(key))
{
dict.Add(key, value);
}
この方法は、重複していたら追加しないという方針です。
特定のキーは1回しか追加したくないという場面では、非常に有効な手段です。
方法3:TryAdd()を使って安全に追加(.NET Core 2.0以降)
dict.TryAdd(key, value);
TryAdd()
は 追加に成功すれば true
、すでにキーがあれば false
を返す便利なメソッドです。
例外をスローせず、成功・失敗を自分で判定できるので、コードがすっきり書けます。
方法4:LINQのToDictionary()を使うときはGroupByで重複を回避
var grouped = items.GroupBy(x => x.Key);
var dict = grouped.ToDictionary(g => g.Key, g => g.First());
このように、GroupBy
を使って同じキーをまとめてから、代表となる1件だけを ToDictionary()
に変換すれば、キーの重複による例外を回避できます。
他にも、重複している値をリストにまとめたい場合は ToLookup()
の使用も検討できます。
方法5:そもそもデータに重複があるか事前に確認する
ときには、「プログラムではなく、そもそも元データに問題がある」という場合もあります。
たとえばCSVやDBに、同じIDのレコードが2件あった・・・なんてことも。
私の場合はこのパターンでした。
そのため、ToDictionary()
を使う前などには、重複キーのチェックを行うのも立派な防御策です。
var duplicates = items.GroupBy(x => x.Key)
.Where(g => g.Count() > 1);
まとめると・・・
方法 | 特徴 | 注意点 |
---|---|---|
[] で上書き | 手軽に使える | 元の値は失われる |
ContainsKey() | 明示的に確認できる | コードがやや冗長 |
TryAdd() | 例外が出ず安心 | .NET Core 以降 |
GroupBy → ToDictionary | データ変換時に安全 | ひと手間かかる |
重複チェック | 根本的な対策 | データ量が多いと処理が重くなることも |
どの方法を選ぶかは、「同じキーが存在していたらどうしたいか」に応じて変わります。
「上書きするのか」「無視するのか」「エラーにしたいのか」――それぞれの意図に合った対処法を選ぶことが大切です。
おわりに
「同一のキーを含む項目がすでに追加されています」というC#のエラーは、一見難しそうに見えますが、実はとてもシンプルな原因から起きています。
ポイントはただ一つ。
Dictionaryに、すでに存在しているキーをもう一度追加しようとしたときに発生する
ということです。
このエラーは、以下のような場面で特に起こりやすいです。
回避するための方法としては、
といった方法が有効です。
プログラミングでは「思ったより単純な理由で動かない」ということがよくあります。
このエラーもそのひとつ。「キーの重複」というルールをしっかり理解すれば、怖くありません。
同じようなエラーで困っている方がいたら、ぜひこの記事をシェアしてあげてくださいね。
C#エンジニアとして、もっと自分の力を活かしたいあなたへ
「このまま今の職場にいて、成長できるんだろうか?」
C#を使っている方なら、一度はそう感じたことがあるかもしれません。
実は今、C#/.NETエンジニアの市場価値は高まっており、
年収アップ・フルリモート・自社開発企業など、選べる選択肢は確実に増えています。
もし今後、C#を活かして働きたい、あるいは開発現場で経験を積みたいとお考えなら…
自分に合った転職サービスを早めに知っておくことが大きな武器になります。
現役エンジニアからのサポート付き・無料で学べるスクール・社内SE特化の求人など、
2025年注目の転職支援サービスを厳選したまとめ記事をこちらで紹介しています👇
コメント