关于运算符重载:未调用C#GetHashCode / Equals覆盖

C# GetHashCode/Equals override not called

我面临一个GetHashCode和Equals的问题,我已经为一个类重写了它。我使用操作符==来验证两者是否相等,我希望这将同时调用getHashCode和equals,如果它们的哈希代码相同,以验证它们是否确实相等。

但令我惊讶的是,两人都没有被召唤,平等测试的结果是错误的(尽管事实上应该是正确的)。

重写代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    public class User : ActiveRecordBase<User>

        [...]

        public override int GetHashCode()
        {
            return Id;
        }

        public override bool Equals(object obj)
        {
            User user = (User)obj;
            if (user == null)
            {
                return false;
            }

            return user.Id == Id;
        }
    }

平等检查:

1
2
    if (x == y) // x and y are both of the same User class
    // I'd expect this test to call both GetHashCode and Equals


操作员==.GetHashCode().Equals()完全分离。

您可能对Microsoft有关重载equals()和operator==的指导原则感兴趣。

简短的版本是:使用.Equals()实现相等比较。使用操作符==进行身份比较,或者如果要创建不可变类型(其中每个相同的实例都可以被视为有效相同)。另外,.Equals()是一个虚拟方法,可以被子类重写,但是操作符==取决于使用它的表达式的编译时类型。

最后,为了保持一致,在任何时候执行.Equals()都可以执行.GetHashCode()。超载操作员!=,任何时候超载操作员==


也许在您的User类中再添加一个方法。

1
2
3
4
5
6
    public virtual bool Equals(User other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.Id == Id;
    }