Why does Dictionary.ContainsKey throw ArgumentNullException?

13,633

Solution 1

If ContainsKey(null) returned false it would give the misleading impression that null keys are allowed..

Solution 2

This is how it is implemented: (Source)

public bool ContainsKey(TKey key) {
    return FindEntry(key) >= 0;
}

And the method FindEntry as:

private int FindEntry(TKey key) {
    if( key == null) {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }

    if (buckets != null) {
        int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
        for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
            if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
        }
    }
    return -1;
}

Since having a null value as key in dictionary is not allowed.

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add(null, 10);

The above would produce an exception:

Value cannot be null. Parameter name: key

For your question:

Wouldn't it be more practical if it just returned false?

Someone from Microsoft could probably reply that. But IMO, since adding a null value for key is not allowed there is no point in checking for null key in ContainsKey

Share:
13,633

Related videos on Youtube

Marcin Kaczmarek
Author by

Marcin Kaczmarek

Updated on September 14, 2022

Comments

  • Marcin Kaczmarek
    Marcin Kaczmarek about 1 year

    The documentation states that bool Dictionary<TKey, TValue>.ContainsKey(TKey key) throws an exception in case a null key is passed. Could anyone give a reason for that? Wouldn't it be more practical if it just returned false?

    • Panagiotis Kanavos
      Panagiotis Kanavos almost 10 years
      A null key is no value at all. It can never be used as a valid key so it can never be considered a valid input.
    • plinth
      plinth almost 10 years
      What is the value of null.GetHashCode()?
    • Servy
      Servy almost 10 years
      @plinth it is whatever the IEqualityComparer says it is =p. It's actually entirely viable to choose to write a dictionary that accepts null keys, the library just didn't choose to do that.
    • supercat
      supercat almost 10 years
      @Luaan: Every generic type T must either be a reference type, in which case it may be directly compared to null, a nullable type, in which case comparison to null can be "compared" to null using a HasValue check, or a structure type in which case a widening conversion will exist to T?, which may then be "compared" to null. To actually box the key if it's a non-nullable value type would be a little silly; it would seem either the JIT should optimize that away or a NullChecker<T>.IsNull method should be able to expedite the test.
  • supercat
    supercat almost 10 years
    I expect the sole reason is probably that while IEquatable<T>.GetHashCode(T) could have been specified to return a constant when given a null value, it wasn't. If a Dictionary's call to IEquatable<T> is going to throw an exception when given a null argument, it would be better to have the exception thrown from Dictionary, giving the name of its parameter, than from IEquatable<T>.GetHashCode().