C# DictionaryのRemoveで要素を削除する方法|キー指定・全削除も解説

はじめに

C#でキーと値のペアを扱うときによく使われるのがDictionary<TKey, TValue>です。ユーザーIDに対するユーザー名、商品コードに対する商品情報、設定名に対する設定値など、キーを使って値を高速に取り出したい場面で便利です。

一方で、登録したデータが不要になったときは、Dictionaryから要素を削除する必要があります。そのときによく使うのがRemoveメソッドです。

この記事では、C#のDictionaryでRemoveを使って要素を削除する基本から、キー指定での削除、全削除、条件に一致する要素の削除、よくあるエラーや実践的な書き方まで解説します。

1. C#のDictionaryで要素を削除する基本

1-1. Dictionaryとは何か

Dictionary<TKey, TValue>は、キーと値をセットで管理するコレクションです。キーを指定すると、それに対応する値を取得できます。

たとえば、次のように文字列のキーに対して整数の値を持つDictionaryを作成できます。

C#
Dictionary<string, int> scores = new Dictionary<string, int>();

scores.Add("Alice", 90);
scores.Add("Bob", 75);
scores.Add("Charlie", 82);

この例では、"Alice""Bob""Charlie"がキーで、907582が値です。

Dictionaryでは、キーは重複できません。同じキーを追加しようとするとエラーになります。そのため、キーを使って特定の要素を一意に管理したい場合に向いています。

1-2. Dictionaryから要素を削除する主な方法

C#のDictionaryから要素を削除する方法には、主に次のようなものがあります。

C#
dictionary.Remove(key);
dictionary.Clear();

Removeは、指定したキーに対応する1件の要素を削除します。

一方、ClearはDictionary内のすべての要素を削除します。

つまり、特定のキーだけ削除したい場合はRemove、Dictionaryを空にしたい場合はClearを使います。

1-3. Removeメソッドでできること

Removeメソッドを使うと、指定したキーに対応する要素をDictionaryから削除できます。

C#
scores.Remove("Bob");

このコードを実行すると、キーが"Bob"の要素がDictionaryから削除されます。

削除後のDictionaryには、"Alice""Charlie"だけが残ります。

C#
foreach (var score in scores)
{
Console.WriteLine($"{score.Key}: {score.Value}");
}

出力例は次のようになります。

C#
Alice: 90
Charlie: 82

1-4. Removeを使う場面

Removeは、特定のデータだけをDictionaryから取り除きたいときに使います。

たとえば、次のような場面です。

C#
// ログアウトしたユーザーのセッション情報を削除する
sessions.Remove(userId);

// 販売終了した商品の情報を削除する
products.Remove(productId);

// キャッシュから不要になったデータを削除する
cache.Remove(cacheKey);

Dictionaryはキーを使ってデータを管理するため、削除時も基本的にはキーを指定します。値を直接指定して削除するのではなく、キーを指定して削除する点を理解しておくと、Dictionaryの削除処理が書きやすくなります。

2. DictionaryのRemoveでキーを指定して要素を削除する方法

2-1. Removeメソッドの基本構文

DictionaryのRemoveメソッドの基本構文は次のとおりです。

C#
dictionary.Remove(key);

たとえば、キーの型がstring、値の型がintのDictionaryであれば、次のように書きます。

C#
Dictionary<string, int> scores = new Dictionary<string, int>();

scores.Add("Alice", 90);
scores.Add("Bob", 75);

scores.Remove("Bob");

Removeには、削除したい要素のキーを渡します。値ではなくキーを指定する点に注意してください。

2-2. キーを指定して1件削除するサンプルコード

次のコードでは、Dictionaryからキー"banana"の要素を削除しています。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 }
};

prices.Remove("banana");

foreach (var item in prices)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}

出力結果は次のようになります。

C#
apple: 120
orange: 100

"banana"に対応する要素が削除されていることがわかります。

2-3. Removeの戻り値で削除できたか判定する

Removeメソッドは、削除に成功したかどうかをboolで返します。

キーが存在して削除できた場合はtrue、キーが存在しなかった場合はfalseです。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 }
};

bool removed = prices.Remove("banana");

if (removed)
{
Console.WriteLine("削除しました。");
}
else
{
Console.WriteLine("指定したキーは存在しません。");
}

出力結果は次のようになります。

C#
削除しました。

このように、Removeの戻り値を使えば、削除できた場合とできなかった場合で処理を分けられます。

2-4. 存在しないキーを指定した場合の動作

DictionaryのRemoveで存在しないキーを指定しても、例外は発生しません。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 }
};

bool removed = prices.Remove("orange");

Console.WriteLine(removed);

出力結果は次のようになります。

C#
False

キー"orange"はDictionary内に存在しないため、削除は行われず、戻り値はfalseになります。

そのため、単に「存在すれば削除する」という処理であれば、事前にContainsKeyで確認しなくても問題ありません。

C#
prices.Remove("orange");

このように書いても、存在しないキーを指定しただけでエラーになることはありません。

3. Dictionaryの要素をすべて削除する方法

3-1. Clearメソッドで全削除する

Dictionaryの要素をすべて削除したい場合は、RemoveではなくClearメソッドを使います。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 }
};

prices.Clear();

Console.WriteLine(prices.Count);

出力結果は次のようになります。

C#
0

Clearを実行すると、Dictionary内のすべての要素が削除されます。

3-2. RemoveとClearの違い

RemoveClearの違いは、削除対象の範囲です。

Removeは、指定したキーに対応する1件の要素を削除します。

C#
prices.Remove("apple");

一方、ClearはDictionary内の要素をすべて削除します。

C#
prices.Clear();

特定のキーだけ削除したい場合はRemove、Dictionaryを空にしたい場合はClearを使うと覚えておくとよいでしょう。

3-3. 全削除後のCountの確認方法

Dictionaryに現在いくつの要素が入っているかは、Countプロパティで確認できます。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 }
};

Console.WriteLine(prices.Count);

prices.Clear();

Console.WriteLine(prices.Count);

出力結果は次のようになります。

C#
3
0

Clearを実行する前は3件、実行後は0件になっています。

削除処理の結果を確認したい場合は、Countを使うとわかりやすくなります。

3-4. Dictionary自体をnullにする方法との違い

Dictionaryの要素をすべて削除する方法として、次のように変数にnullを代入するコードを見かけることがあります。

C#
prices = null;

これはDictionaryの中身を空にしているのではなく、変数がDictionaryのインスタンスを参照しない状態にしているだけです。

そのため、nullにしたあとにDictionaryを使おうとすると、NullReferenceExceptionが発生します。

C#
prices = null;

// NullReferenceExceptionが発生する
Console.WriteLine(prices.Count);

一方、Clearを使った場合はDictionaryのインスタンス自体は残ります。

C#
prices.Clear();

Console.WriteLine(prices.Count);

この場合、Count0になり、Dictionaryは空の状態で引き続き使えます。

Dictionaryを再利用したい場合はClear、Dictionaryそのものが不要になった場合は参照を外す、というように使い分けるとよいでしょう。

4. 条件に一致する要素を削除する方法

4-1. 値を条件にして削除する考え方

DictionaryのRemoveはキーを指定して要素を削除するメソッドです。そのため、値を条件にして削除したい場合でも、最終的には削除対象のキーを取得してからRemoveを呼び出します。

たとえば、「価格が100円未満の商品を削除したい」という場合、次の流れになります。

C#
// 1. 条件に一致する要素のキーを取得する
// 2. 取得したキーを使ってRemoveする

Dictionaryから値を直接指定して削除する専用メソッドはありません。条件削除では、削除対象のキーを先に集めるのが基本です。

4-2. Whereで削除対象のキーを取得する

LINQのWhereを使うと、条件に一致する要素を抽出できます。

C#
var keysToRemove = prices
.Where(x => x.Value < 100)
.Select(x => x.Key)
.ToList();

このコードでは、値が100未満の要素を探し、そのキーだけをリストにしています。

x.KeyはDictionaryのキー、x.ValueはDictionaryの値を表します。

4-3. foreach中にRemoveするときの注意点

Dictionaryをforeachで列挙している途中に、そのDictionaryに対してRemoveを実行すると、InvalidOperationExceptionが発生することがあります。

たとえば、次のようなコードは避けるべきです。

C#
foreach (var item in prices)
{
if (item.Value < 100)
{
prices.Remove(item.Key);
}
}

Dictionaryを列挙している最中にコレクションの内容を変更しているため、エラーの原因になります。

安全に削除するには、削除対象のキーを先に別のリストにしてから、そのリストを使って削除します。

4-4. ToListを使って安全に削除するサンプルコード

条件に一致する要素を安全に削除するには、ToListを使って削除対象のキーを先に確定させます。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 },
{ "grape", 90 }
};

var keysToRemove = prices
.Where(x => x.Value < 100)
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
prices.Remove(key);
}

foreach (var item in prices)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}

出力結果は次のようになります。

C#
apple: 120
orange: 100

"banana""grape"は値が100未満なので削除されています。

ポイントは、Dictionaryを直接列挙しながら削除しないことです。先に削除対象のキー一覧を作ってから、そのキー一覧に対してforeachを行えば安全に削除できます。

5. DictionaryのRemoveでよくあるエラーと注意点

5-1. foreach中に削除してInvalidOperationExceptionが起きる原因

Dictionaryをforeachで回している途中にRemoveを呼び出すと、次のような例外が発生することがあります。

C#
System.InvalidOperationException

これは、列挙中のコレクションが変更されたためです。

たとえば、次のコードは問題があります。

C#
foreach (var item in prices)
{
if (item.Value < 100)
{
prices.Remove(item.Key);
}
}

foreachはDictionaryの状態を前提に順番に要素を取り出しています。その途中でDictionaryの要素数が変わると、列挙処理を続けられなくなるため、例外が発生します。

この問題を避けるには、次のように削除対象のキーを先にリスト化します。

C#
var keysToRemove = prices
.Where(x => x.Value < 100)
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
prices.Remove(key);
}

条件削除では、この書き方を基本として覚えておくと安全です。

5-2. 存在確認にContainsKeyは必要か

Dictionaryからキーを指定して削除する場合、事前にContainsKeyで存在確認をするコードもあります。

C#
if (prices.ContainsKey("apple"))
{
prices.Remove("apple");
}

この書き方でも問題ありませんが、削除できたかどうかを知りたいだけなら、Removeの戻り値を使うほうが簡潔です。

C#
if (prices.Remove("apple"))
{
Console.WriteLine("削除しました。");
}
else
{
Console.WriteLine("キーが存在しません。");
}

Removeは、キーが存在しない場合でも例外を投げずにfalseを返します。そのため、多くの場合はContainsKeyを先に呼ばなくても十分です。

ただし、削除前にキーの存在を使って別の処理をしたい場合は、ContainsKeyを使っても問題ありません。

5-3. nullキーやnull値を扱う場合の注意点

Dictionaryでnullを扱う場合は、キーと値を分けて考える必要があります。

まず、参照型の値にはnullを入れられます。

C#
Dictionary<string, string?> users = new Dictionary<string, string?>
{
{ "001", "Alice" },
{ "002", null }
};

この場合、キー"002"に対応する値はnullです。値がnullであっても、キーを指定すれば削除できます。

C#
users.Remove("002");

一方、キーにnullを使うことはできません。

C#
Dictionary<string, int> scores = new Dictionary<string, int>();

// ArgumentNullExceptionが発生する
scores.Remove(null);

キーの型がstringなどの参照型であっても、Dictionaryのキーとしてnullを指定することはできません。削除処理でキーがnullになる可能性がある場合は、事前にチェックしておくと安全です。

C#
string? key = GetKey();

if (key != null)
{
scores.Remove(key);
}

5-4. 削除後にDictionaryの件数を確認する方法

削除後にDictionaryの件数を確認したい場合は、Countプロパティを使います。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "Alice", 90 },
{ "Bob", 75 },
{ "Charlie", 82 }
};

scores.Remove("Bob");

Console.WriteLine(scores.Count);

出力結果は次のようになります。

C#
2

Removeで1件削除されたため、件数は2件になります。

削除できたかどうかを確認したい場合はRemoveの戻り値、削除後の件数を確認したい場合はCountを使うとよいでしょう。

6. Removeメソッドの実践的な使い方

6-1. キャッシュから不要なデータを削除する

Dictionaryは、簡易的なキャッシュとして使われることがあります。たとえば、商品IDをキーにして商品名を一時的に保持するケースです。

C#
Dictionary<int, string> productCache = new Dictionary<int, string>
{
{ 1, "ノートPC" },
{ 2, "マウス" },
{ 3, "キーボード" }
};

int productId = 2;

productCache.Remove(productId);

このコードでは、商品ID2のキャッシュを削除しています。

削除できたかどうかをログに残したい場合は、戻り値を使います。

C#
if (productCache.Remove(productId))
{
Console.WriteLine("キャッシュを削除しました。");
}
else
{
Console.WriteLine("キャッシュは存在しませんでした。");
}

6-2. ユーザーIDや商品IDをキーにして削除する

Dictionaryでは、ユーザーIDや商品IDのような一意の値をキーにすることがよくあります。

C#
Dictionary<int, string> users = new Dictionary<int, string>
{
{ 101, "Alice" },
{ 102, "Bob" },
{ 103, "Charlie" }
};

int userId = 102;

users.Remove(userId);

このコードでは、ユーザーID102のユーザーを削除しています。

IDをキーにしておくと、削除対象を明確に指定できます。

C#
bool removed = users.Remove(userId);

Console.WriteLine(removed ? "ユーザーを削除しました。" : "ユーザーが見つかりません。");

業務アプリケーションでも、商品ID、注文ID、会員IDなどをキーにしてDictionaryを扱うケースは多くあります。

6-3. 重複チェック用Dictionaryから要素を削除する

Dictionaryは、重複チェックにも利用できます。

たとえば、すでに処理したメールアドレスをDictionaryで管理する場合を考えます。

C#
Dictionary<string, bool> processedEmails = new Dictionary<string, bool>
{
{ "alice@example.com", true },
{ "bob@example.com", true }
};

string email = "bob@example.com";

processedEmails.Remove(email);

このコードでは、"bob@example.com"を処理済みリストから削除しています。

再処理を許可したい場合や、対象外になったデータを管理対象から外したい場合に使えます。

なお、値を使わずキーの存在だけを管理したい場合は、HashSet<T>の利用も検討できます。ただし、キーに対して何らかの値も持たせたい場合はDictionaryが便利です。

6-4. TryGetValueと組み合わせて削除前に値を取得する

削除する前に、削除対象の値を確認したい場合はTryGetValueと組み合わせます。

C#
Dictionary<int, string> users = new Dictionary<int, string>
{
{ 101, "Alice" },
{ 102, "Bob" },
{ 103, "Charlie" }
};

int userId = 102;

if (users.TryGetValue(userId, out string? userName))
{
users.Remove(userId);
Console.WriteLine($"{userName}を削除しました。");
}
else
{
Console.WriteLine("ユーザーが見つかりません。");
}

出力結果は次のようになります。

C#
Bobを削除しました。

この書き方は、削除前の値をログに残したい場合や、削除対象の情報を画面に表示したい場合に便利です。

また、C#のバージョンや対象フレームワークによっては、削除と同時に値を取得できるRemove(key, out value)形式も利用できます。

C#
if (users.Remove(userId, out string? removedUserName))
{
Console.WriteLine($"{removedUserName}を削除しました。");
}
else
{
Console.WriteLine("ユーザーが見つかりません。");
}

この形式を使うと、値の取得と削除をまとめて書けるため、コードを簡潔にできます。

7. Dictionaryの削除処理をわかりやすく書くコツ

7-1. 削除対象のキー名を明確にする

DictionaryのRemoveではキーを指定して削除するため、削除対象のキーが何を表しているのかをわかりやすくすることが大切です。

たとえば、次のような変数名では意味が少し曖昧です。

C#
int id = 102;

users.Remove(id);

ユーザーIDを表すなら、次のように書くほうが読みやすくなります。

C#
int userId = 102;

users.Remove(userId);

商品IDであればproductId、注文IDであればorderIdのように、キーの意味がわかる名前にすると、削除処理の意図が明確になります。

7-2. Removeの戻り値を活用して分岐を書く

Removeの戻り値を使うと、削除できた場合とできなかった場合で処理を分けられます。

C#
if (users.Remove(userId))
{
Console.WriteLine("ユーザーを削除しました。");
}
else
{
Console.WriteLine("指定されたユーザーは存在しません。");
}

この書き方にすると、ContainsKeyで事前確認してからRemoveするよりも簡潔です。

C#
if (users.ContainsKey(userId))
{
users.Remove(userId);
}

もちろん、削除前に値を確認したい場合や、存在する場合だけ別の処理をしたい場合はContainsKeyTryGetValueを使っても構いません。

ただ、単純に削除できたかを判定したいだけなら、Removeの戻り値を活用するのがおすすめです。

7-3. 条件削除では削除対象リストを先に作る

条件に一致する要素を削除する場合は、削除対象のキーを先にリスト化します。

C#
var keysToRemove = users
.Where(x => x.Value.StartsWith("A"))
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
users.Remove(key);
}

このように、削除対象リストを作ってからRemoveすることで、foreach中にDictionaryを変更する問題を避けられます。

条件削除では、次の流れを意識すると安全です。

C#
// 1. 条件に一致するキーを集める
// 2. 集めたキーをforeachで回す
// 3. Removeで削除する

7-4. 可読性を高めるメソッド化の例

削除処理が複数の場所に出てくる場合は、メソッド化すると読みやすくなります。

C#
static bool RemoveUser(Dictionary<int, string> users, int userId)
{
return users.Remove(userId);
}

使う側は次のように書けます。

C#
if (RemoveUser(users, userId))
{
Console.WriteLine("ユーザーを削除しました。");
}
else
{
Console.WriteLine("ユーザーが見つかりません。");
}

条件削除もメソッド化できます。

C#
static void RemoveUsersStartingWith(
Dictionary<int, string> users,
string prefix)
{
var keysToRemove = users
.Where(x => x.Value.StartsWith(prefix))
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
users.Remove(key);
}
}

呼び出し側は次のようになります。

C#
RemoveUsersStartingWith(users, "A");

処理の意図がメソッド名に表れるため、コード全体の可読性が高くなります。

8. DictionaryのRemoveに関するよくある質問

8-1. Dictionaryから値を指定して削除できる?

DictionaryのRemoveはキーを指定して削除するメソッドです。そのため、値だけを指定して直接削除することはできません。

値を条件にして削除したい場合は、値に一致する要素のキーを探してから、そのキーを使って削除します。

C#
Dictionary<string, int> prices = new Dictionary<string, int>
{
{ "apple", 120 },
{ "banana", 80 },
{ "orange", 100 }
};

var keysToRemove = prices
.Where(x => x.Value == 80)
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
prices.Remove(key);
}

このコードでは、値が80の要素を削除しています。

値は重複する可能性がありますが、キーは重複しません。そのため、値を条件にする場合でも、最終的にはキーを使って削除します。

8-2. Removeで削除した要素は復元できる?

Removeで削除した要素は、Dictionaryから取り除かれます。Dictionary自体には、削除した要素を自動的に復元する機能はありません。

復元したい可能性がある場合は、削除前に値を別の変数に退避しておきます。

C#
if (users.TryGetValue(userId, out string? userName))
{
users.Remove(userId);

// 必要であれば後で戻せる
users.Add(userId, userName);
}

または、削除前に別のDictionaryへバックアップする方法もあります。

C#
Dictionary<int, string> removedUsers = new Dictionary<int, string>();

if (users.TryGetValue(userId, out string? userName))
{
removedUsers[userId] = userName;
users.Remove(userId);
}

削除後に復元する可能性がある処理では、削除前にデータを保存しておくことが重要です。

8-3. RemoveとClearはどちらを使うべき?

特定のキーだけ削除したい場合はRemoveを使います。

C#
users.Remove(userId);

Dictionary内のすべての要素を削除したい場合はClearを使います。

C#
users.Clear();

1件または一部の要素を削除するならRemove、すべて削除するならClearと考えるとわかりやすいです。

条件に一致する複数の要素を削除したい場合は、削除対象のキーをリスト化してからRemoveを繰り返します。

C#
var keysToRemove = users
.Where(x => x.Value.Contains("test"))
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
users.Remove(key);
}

8-4. Dictionaryの削除処理はパフォーマンスに影響する?

Dictionaryはキーを使った検索や削除が高速なコレクションです。通常の用途で、キーを指定してRemoveする処理が大きな問題になることは多くありません。

ただし、大量のデータに対して何度も条件削除を行う場合は、処理の書き方に注意が必要です。

たとえば、条件削除では次のように削除対象のキーを一度リスト化します。

C#
var keysToRemove = dictionary
.Where(x => ShouldRemove(x))
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
dictionary.Remove(key);
}

この方法は安全ですが、削除対象のキーリストを作るため、その分のメモリを使います。

多くのケースでは問題ありませんが、非常に大きなDictionaryを扱う場合は、データ構造や削除タイミングを見直すことも検討しましょう。

また、すべての要素を削除する場合は、Removeを繰り返すよりClearを使うほうが簡潔です。

C#
dictionary.Clear();

目的に合わせてRemoveClearを使い分けることで、読みやすく効率的なコードになります。

まとめ

C#のDictionaryで要素を削除する場合、基本的にはRemoveメソッドを使います。

Removeはキーを指定して1件の要素を削除するメソッドです。

C#
dictionary.Remove(key);

削除できたかどうかを判定したい場合は、戻り値を使います。

C#
if (dictionary.Remove(key))
{
Console.WriteLine("削除しました。");
}
else
{
Console.WriteLine("キーが存在しません。");
}

Dictionary内の要素をすべて削除したい場合は、RemoveではなくClearを使います。

C#
dictionary.Clear();

値や条件に一致する要素を削除したい場合は、削除対象のキーを先に取得してからRemoveします。

C#
var keysToRemove = dictionary
.Where(x => x.Value == targetValue)
.Select(x => x.Key)
.ToList();

foreach (var key in keysToRemove)
{
dictionary.Remove(key);
}

foreachでDictionaryを列挙している途中に直接Removeすると、InvalidOperationExceptionの原因になることがあります。条件削除では、削除対象のキーを先にリスト化するのが安全です。

C#のDictionary削除処理では、次の使い分けを覚えておきましょう。

C#
// キーを指定して1件削除
dictionary.Remove(key);

// すべて削除
dictionary.Clear();

// 削除後の件数を確認
dictionary.Count;

Removeの戻り値やCountを活用すると、削除できたかどうかをわかりやすく判定できます。Dictionaryの削除処理を正しく使い分けて、読みやすく安全なC#コードを書きましょう。