C# 继承相等比较器

C# 继承相等比较器,c#,.net,linq,C#,.net,Linq,我有一门顾客课 public class Customer { private string _id; private string _name; // some more properties follow 我继承了EqualityComparer表单MyEqualityComparer(客户的)。 我打算在LINQ查询中使用此选项。 MyQualityComparer用于两个对象之间的部分检查。 如果customer.id和customer.name匹配,我将平等

我有一门顾客课

public class Customer
{
    private string _id;
    private string _name;
    // some more properties follow 
我继承了EqualityComparer表单MyEqualityComparer(客户的)。
我打算在LINQ查询中使用此选项。
MyQualityComparer用于两个对象之间的部分检查。
如果customer.id和customer.name匹配,我将平等对待对象

public class MyComparer : System.Collections.Generic.EqualityComparer<Customer>
{
    public override bool Equals(Customer x, Customer y)
    {
        if (x.Id == y.Id && x.Name == y.Name)
            return true;
        else
            return false;
    }

    public override int GetHashCode(Customer obj)
    {
        return string.Concat(obj.Id,obj.Name).GetHashCode();
    }

}
公共类MyComparer:System.Collections.Generic.EqualityComparer
{
公共覆盖布尔等于(客户x、客户y)
{
if(x.Id==y.Id&&x.Name==y.Name)
返回true;
其他的
返回false;
}
公共覆盖int GetHashCode(客户obj)
{
返回string.Concat(obj.Id,obj.Name).GetHashCode();
}
}
我提到过。
我对串接字符串并将其用作哈希代码有点不确定。

这是我想做的安全可靠的事情吗

您应该从可能的“冲突”的角度来看待它,例如,当两个不同的对象获得相同的哈希代码时。这可能是“1,2any”和“12,any”等对的情况,这些对中的值是“id”和“name”。如果您的数据无法实现这一点,那么您可以继续。否则,您可以将其更改为:

return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
有关基于多个字段返回一个哈希代码的简单方法,请参见

话虽如此,我不会从
EqualityComparer
自己那里派生,我只会直接实现
IEqualityComparer
。除了实现非通用的
IEqualityComparer
之外,我不确定
EqualityComparer
在这里真正给了您什么价值

还有几件事:

  • 您应该在Equals中处理空值
  • 您当前的代码可以简化为:

    return x.Id == y.Id && x.Name == y.Name;
    
Equals的更全面实现可能是:

public override bool Equals(Customer x, Customer y)
{
    if (object.ReferenceEquals(x, y))
    {
        return true;
    }
    if (x == null || y == null)
    {
        return false;
    }
    return x.Id == y.Id && x.Name == y.Name;
}
Resharper(JetBrains的神奇重构插件)认为应该是:

public override int GetHashCode(Customer obj)
{
    unchecked
    {
        return ((obj.Id != null ? obj.Id.GetHashCode() : 0) * 397) 
            ^ (obj.Name != null ? obj.Name.GetHashCode() : 0);
    }
}

我必须承认,我几乎总是让Resharper为我生成相等和哈希代码实现。我已经对它们的实现进行了大量测试,发现它与我手工编写的任何东西一样好。因此,我通常采用不必键入的实现。

不幸的是,不要忘记空检查Id和名称使用异或在相当多的情况下会造成冲突。看见对于Name/ID来说,这可能没什么问题,但总的来说,这不是一个好主意。有什么理由选择397而不是prime吗?我认为它只是为了足够大,可以将hashcode的第一部分放在最终结果的高位。Resharper过去使用29。我不能说我知道是否有一个可靠的理论,或者它只是通过实验选择的。小错误-你需要在与null比较之前将x和y转换为object。请参见@Thracx:仅当您也重载了
=
运算符,并且重载方式无法处理此问题时。是否有理由更喜欢使用三个
返回
而不是一个可返回的逻辑表达式?@NetMage:当天唯一的首选:)我个人喜欢条件运算符,但我知道有些人觉得它很难阅读。我想你不需要条件运算符,只要
&&
|
:)