tags:

views:

161

answers:

3

Can I use C# Dictionary on classes like arrays??

Dictionary<double[],double[]>

I am afraid that it will not be able to tell when arrays are equal...

EDIT:
Will the hashing method in the dictionary take well care of arrays? or just hashing their references?

+4  A: 

For array keys, the dictionary willuse the references for hashing and equality, which probably isn't what you want. This leaves you with two choices: implement a wrapper class for double[], or (better) write something that implements IEqualityComparer and pass it to the Dictionary<T, T> constructor.

JSBangs
If memory serves me correctly (forgive, I am getting old), there [already is a wrapper class for arrays](http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx)
BlueRaja - Danny Pflughoeft
@BlueRaja, does a `List<T>` do equality comparison and hashing over its contents? I don't think that it does.
JSBangs
+2  A: 

Only the array references will be compared. In the following example, the dictionary will have 2 entries even though arrays a and b have the same number of entries and the entry values are equal:

double[] a = new[] { 1.0, 2.1, 3.2 };
double[] b = new[] { 1.0, 2.1, 3.2 };

Dictionary<double[], double[]> d = new Dictionary<double[], double[]>();

d[a] = new [] { 1.1 };
d[b] = new [] { 2.2 };

Console.WriteLine(d.Count);
Console.WriteLine(d[b][0]);
Daniel Renshaw
A: 

I don't think having an array as the key is a good idea, especially if it's big and if your equality logic is based on the content of the array. Because every time you will call GetHashCode, it will have to perform calculations on the whole array, which can take some time if the array is big...

A solution would be to wrap the array in a class which would store the hashcode until the data is modified, so that it isn't recomputed every time :

class ArrayWrapper<T>
{
    private T[] _array;
    public ArrayWrapper(T[] array)
    {
        _array = array;
    }

    private int? _hashcode;
    public override int GetHashCode()
    {
        if (!_hashcode.HasValue)
        {
            _hashcode = ComputeHashCode();
        }
        return _hashcode.Value;
    }

    public override bool Equals(object other)
    {
        // Your equality logic here
    }

    protected virtual int ComputeHashCode()
    {
        // Your hashcode logic here
    }

    public int Length
    {
        get { return _array.Length; }
    }

    public T this[int index]
    {
        get { return _array[index]; }
        set
        {
            _array[index] = value;
            // Invalidate the hashcode when data is modified
            _hashcode = null;
        }
    }
}

So your dictionary would be a Dictionary<ArrayWrapper<double>, ArrayWrapper<double>>. Of course, you might want to add some methods or properties to the wrapper (implement IList<T> for instance)

Thomas Levesque