【C#エラー解決】「同一のキーを含む項目が既に追加」された時の原因と対処法

スポンサーリンク
この記事は約11分で読めます。

C#でプログラムを書いていて、ある日突然、

「同一のキーを含む項目が既に追加されています。」

というエラーが表示されてびっくりしたことはありませんか?

私もはじめてこのエラーに出くわしたとき、「えっ、何のこと?」と固まってしまった記憶があります。

エラーメッセージには「キーが重複していますよ」と書かれているのですが、コードをパッと見ただけでは原因がわからないことがほとんどです。
特に DictionaryToDictionary() を使っているときに、このエラーが急に出てきて、「さっきまで動いてたのに、なんで?」となりがちです。

本記事では、このエラーがなぜ起こるのか、どうすれば回避できるのかを、初心者の方にもわかりやすく、図やサンプルコードを交えながら丁寧に解説していきます。

「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 以降
GroupByToDictionaryデータ変換時に安全ひと手間かかる
重複チェック根本的な対策データ量が多いと処理が重くなることも

どの方法を選ぶかは、「同じキーが存在していたらどうしたいか」に応じて変わります。
「上書きするのか」「無視するのか」「エラーにしたいのか」――それぞれの意図に合った対処法を選ぶことが大切です。

おわりに

「同一のキーを含む項目がすでに追加されています」というC#のエラーは、一見難しそうに見えますが、実はとてもシンプルな原因から起きています。

ポイントはただ一つ。

Dictionaryに、すでに存在しているキーをもう一度追加しようとしたときに発生する

ということです。

このエラーは、以下のような場面で特に起こりやすいです。

  • Dictionary.Add() を使って、同じキーを2回登録しようとしたとき
  • LINQの ToDictionary() で、重複するキーのデータを変換しようとしたとき
  • CSVやデータベースなど、外部データに予期せぬ重複が含まれていたとき

回避するための方法としては、

  • Add() の代わりに dict[key] = value を使って上書きする
  • ContainsKey() で事前にキーの存在を確認してから追加する
  • ToDictionary() を使う場合は、データがユニークかどうかチェックする、あるいは GroupBy を使って重複に対応する

といった方法が有効です。

プログラミングでは「思ったより単純な理由で動かない」ということがよくあります。
このエラーもそのひとつ。「キーの重複」というルールをしっかり理解すれば、怖くありません。

同じようなエラーで困っている方がいたら、ぜひこの記事をシェアしてあげてくださいね。

C#エンジニアとして、もっと自分の力を活かしたいあなたへ

「このまま今の職場にいて、成長できるんだろうか?」

C#を使っている方なら、一度はそう感じたことがあるかもしれません。

実は今、C#/.NETエンジニアの市場価値は高まっており
年収アップ・フルリモート・自社開発企業など、選べる選択肢は確実に増えています。

もし今後、C#を活かして働きたい、あるいは開発現場で経験を積みたいとお考えなら…
自分に合った転職サービスを早めに知っておくことが大きな武器になります。

現役エンジニアからのサポート付き・無料で学べるスクール・社内SE特化の求人など、
2025年注目の転職支援サービスを厳選したまとめ記事をこちらで紹介しています👇

C#
スポンサーリンク
なんくるをフォローする

コメント

タイトルとURLをコピーしました