Why doesn’t Dictionary support null key? [duplicate]

1) Why:
As described before, the problem is that Dictionary requires an implementation of the Object.GetHashCode() method. null does not have an implementation, therefore no hash code associated.

2) Solution: I have used a solution similar to a NullObject pattern using generics that enables you to use the dictionary seamlessly (no need for a different dictionary implementation).

You can will use it, like this:

var dict = new Dictionary<NullObject<Type>, string>();
dict[typeof(int)] = "int type";
dict[typeof(string)] = "string type";
dict[null] = "null type";

Assert.AreEqual("int type", dict[typeof(int)]);
Assert.AreEqual("string type", dict[typeof(string)]);
Assert.AreEqual("null type", dict[null]);

You just need to create this struct once in a lifetime :

public struct NullObject<T>
{
    [DefaultValue(true)]
    private bool isnull;// default property initializers are not supported for structs

    private NullObject(T item, bool isnull) : this()
    {
        this.isnull = isnull;
        this.Item = item;
    }

    public NullObject(T item) : this(item, item == null)
    {
    }

    public static NullObject<T> Null()
    {
        return new NullObject<T>();
    }

    public T Item { get; private set; }

    public bool IsNull()
    {
        return this.isnull;
    }

    public static implicit operator T(NullObject<T> nullObject)
    {
        return nullObject.Item;
    }

    public static implicit operator NullObject<T>(T item)
    {
        return new NullObject<T>(item);
    }

    public override string ToString()
    {
        return (Item != null) ? Item.ToString() : "NULL";
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return this.IsNull();

        if (!(obj is NullObject<T>))
            return false;

        var no = (NullObject<T>)obj;

        if (this.IsNull())
            return no.IsNull();

        if (no.IsNull())
            return false;

        return this.Item.Equals(no.Item);
    }

    public override int GetHashCode()
    {
        if (this.isnull)
            return 0;

        var result = Item.GetHashCode();

        if (result >= 0)
            result++;

        return result;
    }
}

Leave a Comment