C# · 12月 26, 2021

c# – 替换System.Drawing.Point的GetHashCode()方法

如果您打算使用它来描述图像/位图中的“像素”,System.Drawing.Point有一个非常非常糟糕的GetHashCode方法: it is just XOR between the X and Y coordinates.

因此,对于具有2000×2000大小的图像,它具有荒谬的分数,因为只有对角线中的数字才具有相当好的散列.

有些人已经提到了here,使用未经检查的乘法创建一个像样的GetHashCode方法非常容易.

但是,如何在HashSet中使用这个改进的GetHashCode方法呢?
我知道我可以创建自己的类/结构MyPoint并使用这些改进的方法实现它,但是我会破坏我的项目中使用System.Drawing.Point的所有其他代码片段.

是否可以使用某种扩展方法等从System.Drawing.Point“覆盖”该方法?或者“告诉”HashSet使用另一个函数而不是GetHashCode?

目前我正在使用SortedSet< System.Drawing.Point>使用自定义IComparer< Point>存储我的积分.当我想知道集合是否包含Point时,我会调用BinarySearch.它比一个HashSet&LT快; System.Drawing.Point>在一组具有10000个colisions.载有方法,但它没有一样快HashSet的一个好的哈希可能.

解决方法 您可以创建自己的类来实现 IEqualityComparer<Point>,然后将该类提供给 HashSet constructor.

例:

public class MyPointEqualityComparer : IEqualityComparer<Point>{ public bool Equals(Point p1,Point p2) { return p1 == p2; // defer to Point’s existing operator== } public int GetHashCode(Point obj) { return /* your favorite hashcode function here */; }}class Program{ static void Main(string[] args) { // Create hashset with custom hashcode algorithm HashSet<Point> myHashSet = new HashSet<Point>(new MyPointEqualityComparer()); // Same thing also works for dictionary Dictionary<Point,string> myDictionary = new Dictionary<Point,string>(new MyPointEqualityComparer()); }}