Equals和GetHashCode

时间:2009-09-23 16:28:15

标签: c#-3.0

您对此Person类有何看法?像那样覆盖Equals和GetHashCode是一个坏主意或最佳实践吗?

public class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public override bool Equals(object obj) {
        var person = obj as Person;

        return PersonId == person.PersonId;
    }
    public override int GetHashCode() {
        return PersonId;
    }

}

用法:

 static void Main(string[] args) {           

            var list = new List<Person>();
            list.Add(new Person(){ PersonId = 1, Name = "Mike"});
            list.Add(new Person() { PersonId = 2, Name = "Michael Sync" });
            list.Add(new Person(){ PersonId = 1, Name = "Mike"});

            var list1 = new List<Person>();
            list1.Add(new Person() { PersonId = 1, Name = "Mike" });
            list1.Add(new Person() { PersonId = 3, Name = "Julia" });

            var except = list.Except(list1);

            foreach (var item in except) {
                Console.WriteLine(item.Name);
            }
            Console.ReadKey();

        }

3 个答案:

答案 0 :(得分:4)

几点:

  1. 它不是空安全或“不同类型”安全。试试这个:

    new Person().Equals(new Object());
    

    new Person().Equals(null);
    

    邦。

  2. 定义相等操作的类应该通常是不可变的IMO。例如,在将对象用作字典键后更改对象的内容是一件坏事。

  3. 考虑实施IEquatable<Person>

  4. 快速重新实现,仍然假设您希望在ID上基于 完全基于

    public sealed class Person : IEquatable<Person> {
    
        private readonly int personId;
        public int PersonId { get { return personId; }
    
        private readonly string name;
        public string Name { get { return name; } }
    
        public Person(int personId, string name) {
            // Is a null name valid? If not, throw here.
            this.personId = personId;
            this.name = name;
        }
    
        public override bool Equals(object obj) {
            return Equals(obj as Person);
        }
    
        public Equals(Person other) {
            return other != null && other.personId == personId;
        }
    
        public override int GetHashCode() {
            return personId;
        }
    }
    

答案 1 :(得分:4)

是的,这是错误的。您应该永远使用可变属性作为​​GetHashCode计算的一部分。这样做可以让您获得无数难以追踪的错误。

答案 2 :(得分:0)

我可以看到的一个问题是,你会得到很多新的(未保存的)记录(很多零)的冲突 - 除非你做那些连续的-ve id之类的东西......但是你真的需要使用Person作为密钥吗?我个人认为我不会打扰......