C# IEqualityComparer<;T>;和自定义类型

C# IEqualityComparer<;T>;和自定义类型,c#,iequalitycomparer,custom-type,C#,Iequalitycomparer,Custom Type,我试图比较两个列表中的自定义类型,并使用Intersect/Except方法。相等性由此类型的三个字段确定。相等性的基础不仅仅是普通条件(所有字段都包含相同的数据)。当然,我实现了IEqualityComparer。我的问题是,一旦hashCode不相同,GetHashCode()方法返回的值就不相等,这对我没有帮助,因为在我的例子中不是这样 当相等基于多个条件时,有没有办法比较两个自定义对象,以便我可以使用intersect/except/distinct等 这是我的密码: public bo

我试图比较两个
列表中的自定义类型
,并使用
Intersect
/
Except
方法。相等性由此类型的三个字段确定。相等性的基础不仅仅是普通条件(所有字段都包含相同的数据)。当然,我实现了
IEqualityComparer
。我的问题是,一旦hashCode不相同,
GetHashCode()
方法返回的值就不相等,这对我没有帮助,因为在我的例子中不是这样

当相等基于多个条件时,有没有办法比较两个自定义对象,以便我可以使用intersect/except/distinct等

这是我的密码:

public bool Equals(ComparableObject x, ComparableObject y)
{
    if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
        return false;

    if (Object.ReferenceEquals(x, y))
        return true;

    if (x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return true;


    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return true;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;


    return x.Var1.Equals(y.Var1) && x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3);
}


public int GetHashCode(ComparableObject x)
{
    return obj.Var1.GetHashCode() ^ obj.Var2.GetHashCode()^ obj.Var3.GetHashCode()
}

您的工作是提供这样的
GetHashCode()
,即它返回的值对于不同的对象将是不同的(在尽可能多的情况下;对于不相等的对象,您仍然可以返回相同的哈希代码),对于可能相等的对象,它将始终是相同的(在所有情况下,不能为相同的对象返回不同的哈希代码)

例如,如果比较的三个字段中有一个是
int
,则可以将该字段返回为
GetHashCode()


但是,如果很难想出聪明的方法,可以返回一个常量,例如
42
将为所有对象对调用,提供预期的结果,尽管性能最低。

不确定底层类型中的GetHashCode是否存在其他问题,但这是一个自定义类型示例,如果只有前两个字段相同,IEqualityComparer将返回true。这将允许
异常pt
等,以处理该类型

    public class CustomType
    {
        public int Val1 { get; set; }
        public int Val2 { get; set; }
        public int Val3 { get; set; }
    }

    class CustomTypeComparer : IEqualityComparer<CustomType>
    {
        public bool Equals(CustomType x, CustomType y)
        { return x.Val1 == y.Val1 && x.Val2 == y.Val2; }

        public int GetHashCode(CustomType obj)
        { return obj.Val1.GetHashCode() ^ obj.Val2.GetHashCode(); }
    }
公共类自定义类型
{
公共int Val1{get;set;}
公共int Val2{get;set;}
公共int Val3{get;set;}
}
类CustomTypeComparer:IEqualityComparer
{
公共布尔等于(自定义类型x、自定义类型y)
{返回x.Val1==y.Val1&&x.Val2==y.Val2;}
public int GetHashCode(CustomType obj)
{返回obj.Val1.GetHashCode()^obj.Val2.GetHashCode();}
}

如果属性不是简单的类型,如
int
,则可能需要使用
Equals()
而不是
=
来比较对象。

你能发布你的equals方法吗?然后我们可以建议一个兼容的
GetHashCode
实现。或者告诉你
equals
方法是否因为违反了它的约定而被破坏。equal散列码对相等比较是必要的吗?@ViacheslavSmityukh是的,是的
IEqualityComparer
执行两次传递作业,首先它收集所有对象的哈希代码,然后为哈希代码相同的对调用
Equals
。如果它进行简单的比较,如果要知道1000个对象中的哪些对象对是相等的,那么将进行500000次比较。-1为“对于不同的对象,它的返回总是不同的,"这显然是不可能的。如果它总是返回-1,会有任何风险吗?@Bes mM Bes没有风险,只有较差的性能。好的,在我的例子中,我只需要比较一些对象,但我希望不会出现意外的结果?
^
对于许多用途来说都有点次优。通常使用类似于
obj.Val1.GetHashCod的东西e()*37+obj.Val2.GetHashCode();
@CodeInChaos是的,这个例子的目的是紧凑,但肯定是一致的,有比
^
@CodeInChaos更好的方法来组合散列,它可能是次优的,但是如果生成的数字不能存储在Int32中,那么您的建议可能会崩溃。这就是为什么您在未检查的上下文中执行它。使用
未检查关键字或编译器开关。