提问人:Eric Snyder 提问时间:12/2/2021 更新时间:12/2/2021 访问量:168
如何在 [duplicate] 的类中实现 IEquatable<MyType>
How to Implement IEquatable<MyType> in a class that [duplicate]
问:
我需要让继承自 DispenseEntity 的 DispenseFile 类的实例实现 IDispenseEntity 使用自定义相等来比较 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 类:
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 类:
public class DispenseFile : DispenseEntity, IParent, IOutputable, IDispenseFile
{
//Other methods and properties
public override bool Equals(object obj)
{
return base.Equals(obj);
}
}
无论我在 Equals() 方法的 DispenseEntity 类中使用什么,当我尝试时,它都不会被使用:
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 添加到基类并实现 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);
}
}
无论我在 DispenseEntity 类中使用什么 Equals() 方法,它都不会被使用
事实上,它可能不是;关于相交的摘要:
Intersect 使用 HashSet;将列表 B 的内容添加到集合中,然后枚举 A 的内容并尝试将其添加到集合中。如果 Add 返回 false,表示该项已为已知,则生成 A 中的项。在操作结束时,A 中所有也在 B 中的项目都已返回
现在,对于使用默认哈希码提供程序的 HashSet,为了确定它是否包含某个对象 X,它首先获取 X 的哈希码,并查看它所知道的对象,看看是否有任何其他具有相同哈希码的对象。
如果没有具有相同哈希值的已知对象,则认为该集不包含该对象。
如果存在具有相同哈希值的对象,则它使用 Equals 来确定碰撞对象是否确实相同。如果您依赖于 object 的默认哈希码实现,它本质上是项目的内存地址,因此获得相同哈希码的唯一方法是列表 A 和列表 B 共享一个实例
长话短说,如果你不重写 GetHashCode,你会得到一个空的集合结果,因为当所有 of 被添加到集合中时,然后所有 of 都被枚举出来,并且该集合被问到“得到这个了吗?”,答案总是“否” - Equals 永远不需要用于确定实例是否相同,因为哈希值总是不同的, 而交点是(无)_bList
_aList
{ }
..但是,如果您重写了 Equals 和 GetHashCode,您应该可以开始了。你甚至可以将 GetHashCode 重写为(不要;这将是非常低效的),你会看到 Equals 被使用(很多)。return 1
评论
IEquatable<ISomeInterface>
IEquatable
DispenseEntity
IEquatable<DispenseEntity>
)