TryGetValueメソッドで存在しないキー対策【C# Dictionary】

KeyNotFoundExceptionエラーが発性して、「指定されたキーは存在しません」」みたいなエラーメッセージが出でプログラムが動かない経験はないでしょうか。

DictionaryはKeyを[]で指定することで、簡単にValueを取ってきてくれるのですけれども、存在しないKeyを指定するとKeyNotFoundExceptionエラーが発生します。

Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key ‘〇〇〇’ was not present in the dictionary.

今回は、このKeyNotFoundException対策をするための方法を紹介します。

KeyNotFoundException対策方法

KeyNotFoundExceptionを発生させずに、安全にDictinaryから値を取り出す方法は2つです。

  • ContainsKeyメソッドでキーの存在チェックする
  • TryGetValueで存在するキーの値を取得する

それぞれ見てみましょう。

ContainsKeyメソッド + Value取得

まずはConatainsKeyメソッドを使った安全なアクセス方法です。


ConatainsKeyメソッドで存在を確定させて、そのあとキーを指定してとりだしています。

TryGetValueメソッド

続いてTryGetValueメソッドを利用した場合です。


if文はConatainsKeyメソッドを使った場合と一緒ですね。

先ほどはDictionaryにキーを指定してValueを取得しましたが、TryGetValueではキーの存在チェックと同時に、変数itemにValue取り出して渡しています。

速度対決:ContainsKeyメソッド vs TryGetValueメソッド

さて、安全に値を取り出す方法が2つ出てきましたが、どちらを使えばよいのでしょうか。

とりあえず処理速度が速いメソッドを使ってみたいですね。

10%ほどTryGetValueのほうが早い

個人環境での測定結果ですので、あくまで参考とお考え下さい。

100万レコード中から中間地点の1レコードにアクセスして値を取り出すまでを測定したところ、手元の環境では10%ほどTryGetValueのほうが早い結果となりました。

Dictinaryを利用したデータの扱い自体がそもそも高速なので、少量のデータや、少ないアクセス回数ではTryGetValueの恩恵を感じることはないでしょう。

しかしながら、大量のデータ・大量のアクセス回数がある場合や処理時間がシビアに求められる場合は、この TryGetValue の数パーセント差が活きてきます。

TryGetValueメソッドが一回処理が少ない

速度差について、内部コードの要因についても考えてみます。

TryGetValueメソッド、ContainsKeyメソッド、Value取得は内部で同じメソッド(FindEntryメソッド)を呼んでいます。

ContainsKey + Value取得では「FindEntryメソッド」が2回呼ばれるのに対して、TryGetValueメソッドは一度で済むので、速度に差がでているのでしょう。

まとめ

それでは、最後にKeyNotFoundException対策を振り返ります。

  • KeyNotFoundException対策はTryGetValueかContainsKeyを使う
  • TryGetValueメソッドはContainsKey + Value取得を同時に行う
  • TryGetValueメソッドはContainsKey + Value取得より少し速い

昔はTryGetValueのほうが記述が冗長的でしたので、if文の中でしか使わない変数をif文の外に記載する必要がありました。


outに詰め込むための箱を別途変数で用意しなければならなかったためです。

out varの記述がでシンプルに書けるようになったのはうれしいですね。

では。

カテゴリー: C#