【问题标题】:Overriding Equals and GetHashCode doesn't necessarily override equality overloading operator重写 Equals 和 GetHashCode 不一定重写相等重载运算符
【发布时间】:2017-10-17 19:08:42
【问题描述】:

我有以下代码:

public enum ClassType
{
    I,
    II,

}

public enum LocationType
{
    A,
    B
}
public class Person
{
    public LocationType LocType
    { get; set; }
    public ClassType ClaType
    { get; set; }


    public override bool Equals(object obj)
    {
        Person obPer = obj as Person;
        if (obPer == null)
            return false;
        if (LocType != obPer.LocType)
            return false;
        if (ClaType != obPer.ClaType)
            return false;
        return true;

    }

    public override int GetHashCode()
    {
        return LocType.GetHashCode()^ClaType.GetHashCode();
    }

}

  static void Main(string[] args)
    {

        var p1 = new Person()
        {
            ClaType = ClassType.I,
            LocType = LocationType.A
        };


        var p2 = new Person()
        {
            ClaType = ClassType.I,
            LocType = LocationType.A
        };

        bool isEqual1 = p1.Equals(p2);  //true
        bool getHashCodeNum = p1.GetHashCode() == p2.GetHashCode();  //true
        bool isEqual2 = p1 == p2;  //false
    }

我发现isEqual1=truegetHashCodeNum=true,但是isEqual2=false

我希望既然我已经覆盖了EqualsGetHashCode,那么运算符== 应该会自动遵循Equals 的行为,但事实并非如此。有什么原因吗?

【问题讨论】:

  • == 只检查引用相等
  • 由于该语言允许您为您的班级覆盖==,如果您选择不这样做,它不会在幕后这样做。
  • @Damien_The_Unbeliever:请注意,您不是覆盖,而是重载 == 运算符。
  • 你需要实现:public static bool operator ==(Person person1, Person person2)。看起来在 2010 年之前也有人问过同样的问题:stackoverflow.com/questions/4219261/…
  • 您也应该重载 ==(和 !=)运算符。遵循these 指南

标签: c#


【解决方案1】:

==操作员。您可以在两个Persons 上重载 == 运算符,如下所示:

public class Person {

    //..

    public static bool operator == (Person a, Person b)
    {
        if (Object.ReferenceEquals(a,null) && Object.ReferenceEquals(b,null))
            return true;
        if (Object.ReferenceEquals(a,null) || Object.ReferenceEquals(a,null))
            return false;
        return a.LocType == b.LocType && a.ClaType != b.ClaType;
    }

    public static bool operator != (Person a, Person b)
    {
       return ! (a == b);
    }

}

==!=是对的:如果你实现==,你需要实现!=,反之亦然,否则会报错:

错误 CS0216:运算符 Person.operator ==(Person, Person) 还需要定义匹配的运算符 !=

现在,当您比较两个 Persons 时,它应该可以工作。但是请注意,您确实覆盖相等运算符,而是重载它们。因此编译器选择了== 实现(这不是在运行时通过动态绑定完成的)。结果:

bool isEqual2 = p1 == p2;  //true
bool isEqual3 = (object) p1 == p2;  //false
bool isEqual4 = p1 == (object) p2;  //false
bool isEqual5 = (object) p1 == (object) p2;  //false

默认情况下,两个objects 之上的==引用相等,所以这里只有当两个参数是Persons 时,我们检查两个人是否相等。

因此,如果您想通过动态绑定检查相等性,最好使用Equals(..)

【讨论】:

  • 在这个阶段,我通常建议也实施IEquatable<T> 并将所有实际检查放在那里,作为中心位置。然后让==Equals(object) 调用它(在合适的null 检查之后)
  • if (a == null && b == null) 会导致无限循环
猜你喜欢
  • 2011-08-16
  • 2011-01-20
  • 2010-11-16
  • 2019-02-02
  • 2014-10-17
  • 2012-04-07
相关资源
最近更新 更多