简体   繁体   English

Equals,GetHashCode,EqualityComparers和模糊平等

[英]Equals, GetHashCode, EqualityComparers and fuzzy equality

For an object with properties A, B, C, D, StartDate and EndDate if I wanted to implement something where any two objects are equal if they have identical A, B and C and overlapping date range, how would that be done? 对于具有属性A,B,C,D,StartDate和EndDate的对象,如果我想实现任何两个对象相等的东西,如果它们具有相同的A,B和C以及重叠的日期范围,那该怎么办?

I have tried creating an EqualityComparer like so 我试过像这样创建一个EqualityComparer

    public override bool Equals(RateItem x, RateItem y)
    {
        bool equal = true;
        if ((x.A != y.A || x.B != y.B || x.C != y.C ||
            (x.StartDate < y.StartDate && x.EndDate <= y.StartDate) ||
            (x.StartDate > y.StartDate && y.EndDate <= x.StartDate)))
        { equal = false; }
        return equal;
    }

But it seems lots of places in the framework ignore Equals and use GetHashCode and the documentation is not clear on that at all. 但似乎框架中的很多地方都忽略了Equals并使用了GetHashCode,文档根本就不清楚。 When I go to implement GetHashCode I don't know how to make the HashCodes turn out the same without ignoring the dates. 当我去实现GetHashCode时,我不知道如何在不忽略日期的情况下使HashCodes变为相同。

To make it a little more concrete this has to do with project management and rates. 为了使其更具体,这与项目管理和费率有关。 I want to implement a business rule that the same person on the same project in the same role can't have to different rates during the same time period. 我想实现一个业务规则,即同一个角色中同一个项目中的同一个人在同一时间段内不能有不同的费率。 So Bob on Project DeathMarch in the role of DBA can only have one effective bill rate at any given time to log his time. 因此Bob在Project DeathMarch中担任DBA角色,在任何给定时间只能有一个有效的账单费率来记录他的时间。 If he needed to log some hours in the role of QA analyst at a different rate during the same time period that is OK. 如果他需要在同一时间段内以不同的速率记录QA分析师的角色,那就没问题。 This is a massive pre-existing system so changing the domain object structure is not an option. 这是一个庞大的预先存在的系统,因此不能选择更改域对象结构。

This is not possible. 这是不可能的。

Equality in .Net must be transitive, meaning that if a == b and b == c , then a == c . .Net中的平等必须是可传递的,这意味着如果a == bb == c ,那么a == c

It is possible. 有可能的。 The only rule for GetHashCode is that A.GetHashCode() must equal B.GetHashCode() if A == B. The opposite, if A == B A.GetHashCode() == B.GetHashCode() does not have to be true. GetHashCode的唯一规则是A.GetHashCode()必须等于B.GetHashCode()如果A == B.相反,如果A == B A.GetHashCode()== B.GetHashCode()则不一定真正。

So you can simply make GetHashCode like so 所以你可以简单地制作GetHashCode

public override int GetHashCode()
{
    return A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode();
}

GetHashCode is not for identity!! GetHashCode不是为了身份!! It is used for grouping 'similar' objects. 它用于分组“类似”对象。

Proof: 证明:

string a = "a";
string b = "EUKCnPMLpp";
Console.WriteLine("a = '{0}', b = '{1}', Same = {2}", a, b, a == b);
Console.WriteLine("a.GetHashCode() = {0}, b.GetHashCode() = {1}, Same = {2}", a.GetHashCode(), b.GetHashCode(), a.GetHashCode() == b.GetHashCode());

If you are using the items in a hashtable then their GetHashCode method will be used initially to test for equality and if their hashes are found to be equal a call to their Equals method will be made to establish whether they are equal. 如果您正在使用哈希表中的项目,那么最初将使用它们的GetHashCode方法来测试相等性,如果发现它们的哈希值相等,则将调用它们的Equals方法来确定它们是否相等。

From the documentation: 从文档:

"But is that enough for the Hashtable to determine they are identical objects? Unfortunately, no. If the Hashtable finds two objects with the same hash, it calls their Equals method to see whether the two objects are in fact equal. Again, the default implementation of Object.Equals will return false if the two objects are two different instances of the same class. So we need to also add an override of the Equals method to our class. “但这足以让Hashtable确定它们是相同的对象吗?不幸的是,没有。如果Hashtable发现两个具有相同散列的对象,它会调用它们的Equals方法来查看这两个对象是否实际上是相等的。再次,默认如果两个对象是同一个类的两个不同实例,则Object.Equals的实现将返回false。因此我们还需要向我们的类添加Equals方法的重写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM