Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary.ContainsKey misbehave c#

I've got a class Column

public class Column
{
    public int Id { get; private set; }
    public string Name { get; private set; }
    public EPersonalCharacteristicType Type { get; private set; }
    public Column MainColumn { get; private set; }
}

and I've got the following field in another class

Dictionary<Column, string> dictionary

In the middle of execution I get a strange behavior of this dictionary. When I typed

dictionary.ContainsKey(dictionary.Keys.ToList()[1])

I got false.
How on Earth can it be?

UPDATED
my Column class has GetHashCode or Equals Functions. Here are the implementations of them:

public bool Equals(Column other)
{
    if (ReferenceEquals(null, other)) return false;
    if (ReferenceEquals(this, other)) return true;
    return other.Id == Id && Equals(other.Name, Name) && Equals(other.Type, Type) && Equals(other.MainColumn, MainColumn) && Equals(other.childColumns, childColumns);
}

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != typeof (Column)) return false;
    return Equals((Column) obj);
}

public override int GetHashCode()
{
    unchecked
    {
        int result = Id;
        result = (result*397) ^ (Name != null ? Name.GetHashCode() : 0);
        result = (result*397) ^ Type.GetHashCode();
        result = (result*397) ^ (MainColumn != null ? MainColumn.GetHashCode() : 0);
        result = (result*397) ^ (childColumns != null ? childColumns.GetHashCode() : 0);
        return result;
    }
}

public static bool operator ==(Column left, Column right)
{
    return Equals(left, right);
}

public static bool operator !=(Column left, Column right)
{
    return !Equals(left, right);
}
like image 969
StuffHappens Avatar asked Jun 22 '11 09:06

StuffHappens


2 Answers

This is not a general problem but something specific to your code.

UPDATE:
The hash code of the key of a dictionary must not change. This is not the case with your Column class, because as soon as any of its properties are changed, the hash code changes, too.
Documentation:

As long as an object is used as a key in the Dictionary, it must not change in any way that affects its hash value.

The background of this is the following: The dictionary retrieves and stores the hash code of the key at the time it is added. If the hash code of the key changed after that, it is different to the stored hash code and the object will not be seen as equal to the originally inserted key.

like image 119
Daniel Hilgarth Avatar answered Nov 07 '22 17:11

Daniel Hilgarth


If Dictionary<Column, string> is right, then I would guess it's because the type Column is not compatible with how Dictionary<TKey, TValue> checks equality - which is based on comparisons through GetHashCode and Equals - and my guess is that the Column type does not implement these.

Change the key type of the dictionary to something more suited to comparisons and equality. Ideally use a string derived from the column's name.

Update

Based on your code update, my guess is that something about the column has changed since it went into the dictionary that causes its 'live' hash code to change from what it was when it was first added to the Dictionary - so that could be any change in Id, Name, Type, MainColumn or ChildColumns that causes their HashCodes to change.

like image 24
Andras Zoltan Avatar answered Nov 07 '22 16:11

Andras Zoltan