使用条件相等实现IEqualityComparer <T>的GetHashCode

Sam*_*les 5 c# linq set hashcode

我想知道是否有人对此问题有任何建议.

我使用带有自定义IEqualityComparer的intersect和except(Linq)来查询设置差异并设置两个ISyncableUsers序列的交集.

public interface ISyncableUser
{
    string Guid { get; }
    string UserPrincipalName { get; }
}
Run Code Online (Sandbox Code Playgroud)

两个ISyncableUsers是否相等的逻辑是有条件的.条件围绕两个属性Guid和UserPrincipalName中的任何一个是否具有值.解释这种逻辑的最好方法是使用代码.下面是我的客户IEqualityComparer的Equals方法的实现.

public bool Equals(ISyncableUser userA, ISyncableUser userB)
{
    if (userA == null && userB == null)
    {
        return true;
    }

    if (userA == null)
    {
        return false;
    }

    if (userB == null)
    {
        return false;
    }

    if ((!string.IsNullOrWhiteSpace(userA.Guid) && !string.IsNullOrWhiteSpace(userB.Guid)) &&
        userA.Guid == userB.Guid)
    {
        return true;
    }

    if (UsersHaveUpn(userA, userB))
    {
        if (userB.UserPrincipalName.Equals(userA.UserPrincipalName, StringComparison.InvariantCultureIgnoreCase))
        {
            return true;
        }
    }
    return false;
}

private bool UsersHaveUpn(ISyncableUser userA, ISyncableUser userB)
{
    return !string.IsNullOrWhiteSpace(userA.UserPrincipalName)
            && !string.IsNullOrWhiteSpace(userB.UserPrincipalName);
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是实现GetHashCode,以便尊重上面表示的上述条件相等.我能够获得交叉的唯一方法是除了调用按预期工作之外,简单总是从GetHashCode()返回相同的值,强制调用Equals.

 public int GetHashCode(ISyncableUser obj)
 {
     return 0;
 }
Run Code Online (Sandbox Code Playgroud)

这可行,但性能损失是巨大的,如预期的那样.(我已经用非条件相等测试了这个.有两个包含50000个对象的集合,一个正确的哈希码实现允许执行拦截,除了大约40ms.总是返回0的哈希码实现大约需要144000ms(是的,2.4分钟!) )

那么,我将如何在上面的场景中实现GetHashCode()呢?

任何想法都会受到欢迎!

Raw*_*ing 2

如果我没看错的话,你的平等关系是不传递的。想象一下以下三个ISyncableUser

A { Guid: "1", UserPrincipalName: "2" }
B { Guid: "2", UserPrincipalName: "2" }
C { Guid: "2", UserPrincipalName: "1" }
Run Code Online (Sandbox Code Playgroud)
  • A == B因为他们有相同的UserPrincipalName
  • B == C因为他们有相同的Guid
  • A != C因为他们也不分享。

规格来看

Equals方法具有自反性、对称性和传递性也就是说,如果用于将对象与其自身进行比较,则返回true ;对于两个对象为真x,并且y如果对于和为;且对于两个对象为真,并且如果对于和为真,并且对于和也为真yxxzxyyz

如果你的等式关系不一致,你就无法实现支持它的哈希码。

从另一个角度来看:您本质上是在寻找三个功能:

  • G将 GUID 映射到整数(如果您知道 GUID 但 UPN 为空)
  • U将 UPN 映射到整数(如果您知道 UPN 但 GUID 为空)
  • P将 (guid, upn) 对映射到整数(如果您两者都知道)

这样G(g) == U(u) == P(g, u)对于所有gu. g这只有在你完全忽略的情况下才有可能u