GetHashCode()中引用的非只读字段

时间:2013-12-16 05:26:23

标签: c# .net .net-4.0

首先覆盖概念,然后覆盖方法EqualsGetHashCode

主要是我想出了这个“非常简单的代码”:

internal class Person
    {
        public string name;

        public int age;

        public string lname;

        public Person(string name, int age, string lname)
        {
            this.name = name;
            this.age = age;
            this.lname = lname;
        }

        public override bool Equals(object obj)
        {
            var person = obj as Person;
            if (person != null)
            {
                return person.age == this.age && person.name == this.name && person.lname == this.lname;
            }

            return false;
        }

        public override int GetHashCode()
        {
            return this.age.GetHashCode() * this.name.GetHashCode() * this.lname.GetHashCode();
        }
    }

虽然这很有效,但我的“合作开发者”Mr.Resharper给了我一些建议:

  1. GetHashCode()中引用的非只读字段。建议来自这行代码:
  2. return this.age.GetHashCode() * this.name.GetHashCode() * this.lname.GetHashCode();

    1. 我们是否应仅对属性使用GetHashCode?

2 个答案:

答案 0 :(得分:21)

总结评论中讨论的内容:

Hashing旨在为给定对象提供一个不会发生变化的值,无论发生什么变化 - 因此最好只依赖于GetHashCode方法中的只读字段。

首先,我建议只读取namelname字段,因为它们在您的使用方案中可能不会改变。

对于age,这是定期更改的内容,因此最好存储一个DateTime的出生日期,这个日期永远不会改变。那么你也可以只读它。

答案 1 :(得分:3)

如果您更改了哈希计算中使用的字段的值,则在将对象添加到基于字典的哈希容器(例如Dictionary或HashSet)之后,实际上将破坏容器的内部状态。这是为什么?因为对象已基于其初始状态存储在与哈希值相对应的存储桶中。当状态改变时,例如修改了“年龄”后,该对象将继续存在于哈希容器中的旧存储桶中,尽管根据当前的哈希代码这不是正确的存储桶。这会导致非常凌乱的行为和很多头痛。我已经针对这个主题写了一个article,上面有一些非常具体的示例,因此您可能需要查看一下。