Tip12 重写Equals时也要重写GetHashCode

Tip12 重写Equals时也要重写GetHashCode
如果重写Equals方法但不重写GetHashCode方法,在使用如FCL中的Dictionary类时,可能隐含一些潜在的Bug。例如:

        class Person
        {
            public string IDCode { get; private set; }

            public Person(string idCode)
            {
                this.IDCode = idCode;
            }

            public override bool Equals(object obj)
            {
                return IDCode == (obj as Person).IDCode;
            }
        }

        class PersonMoreInfo
        {
            public string SomeInfo { get; set; }
        }

        static void Main(string[] args)
        {
            AddAPerson();
            Person mike = new Person("NB123");

            //Console.WriteLine(mike.GetHashCode());
            //得到的HashCode与AddAPerson中的HashCode不一样

            Console.WriteLine(PersonValues.ContainsKey(mike));
        }

        static void AddAPerson()
        {
            Person mike = new Person("NB123");
            PersonMoreInfo mikeValue = new PersonMoreInfo() { SomeInfo = "Mike's info" };
            PersonValues.Add(mike, mikeValue);
            //Console.WriteLine(mike.GetHashCode());
            Console.WriteLine(PersonValues.ContainsKey(mike));
        }

输出的结果是

True
False

理论上来说,AddAPerson中的mike和Main方法中的mike属于“值相等”,将该“值”作为key放入Dictionary中,再在某处根据mike将mikeValue取出来,这是理所当然的。针对同一个示例,这种结论是正确的,但针对不同的mike示例额,这种结果就有问题了。
原因是基于键值的集合(如Dictionary)是根据Key值的HashCode(调用类型的GetHashCode方法)来查找Value值。

注:GetHashCode方法应该基于只读的属性或特性生成HashCode。

GetHashCode方法存在一个问题:永远只返回一个整型类型,而整型类型的容量无法满足字符串的容量,例如:

string str1 = "NB0903100006";
string str2 = "NB0904140001";
//输出结果是一样的
Console.WriteLine(str1.GetHashCOde());
Console.WriteLine(str2.GetHashCOde());

Person类型对GetHashCode方法稍作改进后可以减少产生相同HashCode的几率。
Person类型的最终版本应该如下:

    class Person : IEquatable<Person>
    {
        public string IDCode { get; private set; }

        public Person(string idCode)
        {
            this.IDCode = idCode;
        }

        public override bool Equals(object obj)
        {
            return IDCode == (obj as Person).IDCode;
        }

        public override int GetHashCode()
        {
            return (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + this.IDCode).GetHashCode();
        }

        public bool Equals(Person other)
        {
            return IDCode == other.IDCode;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值