C#使用.Equals()而不是散列的字典

C#使用.Equals()而不是散列的字典,c#,dictionary,C#,Dictionary,是否有类似字典的数据结构,允许根据为给定类而不是哈希值定义的.Equals()调用添加唯一元素 在我的例子中,我有一个PointD类定义了一个具有十进制X和Y的点。由于十进制类型的性质有点不精确,因此不可能在该点上创建哈希,因为本质上相同的两个点之间的一个小错误将导致哈希值的重大差异 基本上,我希望能够计算每个x,y组合的点数。是否有现有的机制,或者我需要自己实现它?是的,您可以制作自己的IEqualityComparer,并在构建它时将其传递给字典。。。。它不使用Equal,但您可以让它做您自

是否有类似字典的数据结构,允许根据为给定类而不是哈希值定义的.Equals()调用添加唯一元素

在我的例子中,我有一个PointD类定义了一个具有十进制X和Y的点。由于十进制类型的性质有点不精确,因此不可能在该点上创建哈希,因为本质上相同的两个点之间的一个小错误将导致哈希值的重大差异


基本上,我希望能够计算每个x,y组合的点数。是否有现有的机制,或者我需要自己实现它?

是的,您可以制作自己的IEqualityComparer,并在构建它时将其传递给字典。。。。它不使用Equal,但您可以让它做您自己的散列


如果您想在实际的Point类上保留哈希,这会更好一些。

只需覆盖PointD类上的GetHashCode方法以满足您的需要,不需要?

小心。听起来您想要定义相等,以便在特定公差范围内的值被视为相等。如果这样做,Equals将不会是可传递的,但它需要是可传递的,字典才能正常工作

示例:假设x比y小0.8倍公差。他们将被认为是平等的。现在考虑值Z,它比Y大0.8倍的公差。因此y和z也是相等的。但是x和z不相等

GetHashCode必须为两个相等的对象返回相同的值。由于等式在这个系统中是不可传递的,您可以证明GetHashCode需要为所有对象返回相同的值,这会导致您的字典像一个链表一样工作(但存储开销更大,这会被浪费)


您可以通过将所有点舍入到一定程度的精度,并根据舍入值计算哈希代码和等式来解决此问题。当然,这种方法可能有自己的缺陷。

不使用哈希的词典是不可能的。字典需要哈希函数和相等比较器。哈希代码用于获取哈希表中的bucket,相等比较器用于检查bucket中的值。最重要的要求是,比较相等的值也必须具有相同的哈希代码

在你的情况下,我要做的是将点标准化,只使用一定数量的数字。您可以使用该方法来执行此操作。这样,可以保留has/equality组合的所有必要属性


您可以在构造函数中或覆盖
Equals
GetHashCode
方法(您仍然需要)中进行舍入。在构造函数中执行此操作的优点是,您只需执行一次计算,同时仍然在所有地方强制执行需求。如果您的类是可变的,那么您还必须在属性设置器中以及直接修改字段的任何位置执行此操作。

如果您有大量的点,您最好使用类似于
字典的东西,将每个
点d
转换为
点。如果X值在公差范围内,则可能会四舍五入到不同的值,则在
字典中存储四舍五入和四舍五入版本。查找点时,如果Y值使得公差范围内的值可以四舍五入为不同的值,请在表中查找这两个值


请注意,字典操作可能返回一个或两个
List
(只有在Y舍入不明确的情况下才有两个实例;这些列表中的部分或全部
点D
实例可能与实际关注点不匹配,但需要检查的实例数量应该是
字典中总数的一小部分“不要重写哈希代码以提供更适合您的解决方案?浮点类型不精确,十进制不精确。我认为唯一的方法是将数字四舍五入以检查是否相等。@GustavoFreddo十进制和浮点都不精确。例如,两种类型都不能精确表示1/3。嗯,忘记了整个传递性交易……嗯,我考虑到我的目的,您所说的会起作用。我刚刚定义了GetHashCode,将x和y值的字符串散列为3位并连接起来。然后定义了带有一个相当小的容差的Equals函数。对于我的应用程序,我不认为这会引起任何问题。