Re: Key compare in Dictionary

Mike Andrews <[email protected]> Thu, 20 May 2010 05:49:44 -0500
Newsgroups gmane.comp.windows.devel.dotnet.advanced
Message-ID <[email protected]>
You need to override GetHashCode and Equals.  It needs to look something
like this:

    public class KeyData : IEquatable<KeyData> {
        public string F1 { get; set; }
        public int F2 { get; set; }
        public KeyData(string f1, int f2) {
            F1 = f1;
            F2 = f2;
        }

        public bool Equals(KeyData other) {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.F1, F1) && other.F2 == F2;
        }
        public override bool Equals(object obj) {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(KeyData)) return false;
            return Equals((KeyData)obj);
        }
        public override int GetHashCode() {
            unchecked {
                return ((F1 != null ? F1.GetHashCode() : 0) * 397) ^ F2;
            }
        }
        public static bool operator ==(KeyData left, KeyData right) {
            return Equals(left, right);
        }
        public static bool operator !=(KeyData left, KeyData right) {
            return !Equals(left, right);
        }
    }



On Thu, May 20, 2010 at 5:32 AM, David Nicholson <[email protected]>wrote:

> I am using a class as a key to a Dictionary, and the key comparisons are
> not working as I expect. The example below illustrates:
>
> // This is the key of the dictionary
> namespace DictionaryTest
> {
>    using System;
>    public class KeyData : IEquatable<KeyData>
>    {
>        public string F1 { get; set; }
>        public int F2 { get; set; }
>
>        public KeyData(string f1, int f2)
>        {
>            F1 = f1;
>            F2 = f2;
>        }
>
>        bool IEquatable<KeyData>.Equals(KeyData other)
>        {
>            if (String.Compare(F1, other.F1, true) != 0)
>                return false;
>
>            if (F2 != other.F2)
>                return false;
>
>            return true;
>        }
>    }
> }
>
> and I am using it like this:
>
> namespace DictionaryTest
> {
>   using System;
>   using System.Collections.Generic;
>    class Program
>    {
>        static void Main(string[] args)
>        {
>            var d1 = new Dictionary<KeyData, int>();
>
>            d1.Add(new KeyData("a", 1), 1);
>            d1.Add(new KeyData("b", 1), 1);
>
>            KeyData kd = new KeyData("a", 1);
>
>            string mesg;
>            if (d1.ContainsKey(kd))
>                mesg = "Found";
>            else
>                mesg = "Not found";
>
>            Console.WriteLine(mesg);
>        }
>    }
> }
>
> This always returns "Not found", which isn't what I expect. A breakpoint on
> KeyData.Equals is never reached. The documentation for dictionary includes:
>
> "If type TKey implements the System .IEquatable <T> generic interface, the
> default equality comparer uses that implementation"
>
> I wrote an IEqualityComparer<KeyData> and passed that to the dictionary
> constructor, and it works as I expect.
>
> Thanks
> David.
>
> ===================================
> View archives and manage your subscription(s) at
> http://peach.ease.lsoft.com/archives
>

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives