如何在 class 中实现 IEquatable<MyType>

How to Implement IEquatable<MyType> in a class that

我需要让 DispenseFile class 实例继承自实现 IDispenseEntity 的 DispenseEntity 使用自定义相等性来比较 List 中的元素。

我的界面是:

public interface IDispenseEntity : IEquatable<IDispenseEntity>
{
    byte[] Id { get; set; }
    List<byte[]> Key { get; }
    List<byte[]> ParentKey { get; set; }
    double Volume { get; set; }
    public bool DispenseEnabled { get; set; }
    string Name { get; set; }
}

我的 DispenseEntity class:

public class DispenseEntity : IDispenseEntity, IEquatable<IDispenseEntity>
{
    //Other properties and methods
    
    //I've tried - this implements IEquatable:
    public bool Equals(IDispenseEntity other)
    {
        return Id.SequenceEqual(other.Id);
    }

    //I've tried - this overrides default:
    public override bool Equals(object obj)
    {
        return Id.SequenceEqual((obj as IDispenseEntity).Id);
    }
}

我的 DispenseFile class:

public class DispenseFile : DispenseEntity, IParent, IOutputable, IDispenseFile
{
    //Other methods and properties
    
    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }
}

无论我在 DispenseEntity class 中为 Equals() 方法使用什么,当我尝试时它都不会被使用:

List<IDispenseEntity> before = _aList;
List<IDispenseEntity> after = _bList;
var intersect = before.Intersect(after).ToList();

相交列表有零个元素。

我绝对肯定 _aList 和 _bList 都有一个 DispenseFile 实例,它继承了实现 IDispenseEntity 的 DispenseEntity。我编写了测试代码,在 _aList 中找到唯一的 DispenseFile 实体,并在 _bList 中找到 DispenseFile 的单个实例。这两个实例都是单独创建的,并且具有相同的 属性 Id ( new byte[] {1,2,3,4} )

我试过覆盖 Equals。我已经尝试将 IEquatable 添加到基础 class 并实现 equals 和 GetHashCode,但这些都没有被使用。

问题一定出在我身上,我做错了什么?

您甚至不需要实现 IEquatable 任何东西;覆盖 GetHashCode 和 Equals 就足够了

public class DispenseEntity : IDispenseEntity
{
    ...

    public override int GetHashCode()
    {
        return new BigInteger(Id).GetHashCode(); //or your choice
    }

   
    public override bool Equals(object obj)
    {
        return obj is DispenseEntity x && x.Id.SequenceEqual(Id);
    }
}

No matter what I use in DispenseEntity class for Equals() method it does not get used

确实可能不会;关于相交的概要:

Intersect 使用了一个 HashSet;将列表 B 的内容添加到集合中,然后枚举 A 的内容并尝试将其添加到集合中。如果 Add returns 为 false,表示该项目已知,则生成来自 A 的项目。在操作结束时,A 中所有也在 B 中的项目都已返回

现在,对于使用默认哈希码提供程序确定它是否包含某个对象 X 的 HashSet,它首先获取 X 的哈希码并查看它知道的对象以查看是否有任何其他对象具有相同的哈希码。

如果没有已知对象具有相同的哈希值,则认为该集合不包含该对象。

如果存在具有相同散列的对象,则它使用 Equals 来确定碰撞对象是否真的相同。如果你依赖对象的默认哈希码实现,它本质上是项目的内存地址,所以你获得相同哈希码的唯一方法是列表 A 和列表 B 共享一个实例

长话短说,如果您不重写 GetHashCode,您将得到一个空集结果,因为当所有 _bList 都添加到集合中,然后枚举所有 _aList并询问集合“得到这个吗?”答案总是“否”——永远不会 需要 来确定实例是否相同,因为哈希值总是不同的,交集是 { }(没有)

..但是如果你重写了 Equals 和 GetHashCode,你就可以开始了。您甚至可以将 GetHashCode 覆盖为 return 1(不要这样做;这会非常低效)并且您会看到使用了 Equals(很多)..