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

本文关键字:方法 GetHashCode System Drawing Point 替换 | 更新日期: 2023-09-27 17:50:51

System.Drawing.Point有一个非常非常糟糕的GetHashCode方法,如果你打算用它来描述图像/位图中的"像素":它只是X和Y坐标之间的异或。

所以对于一个大小为2000x2000的图像,它有一个荒谬的碰撞数,因为只有对角线上的数字才会有一个像样的哈希值。

正如有些人在这里已经提到的那样,使用未检查的乘法创建一个体面的GetHashCode方法非常容易。

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

是否有可能使用某种扩展方法或类似的方法从System.Drawing.Point"覆盖"方法?或者"告诉"HashSet使用另一个函数而不是GetHashCode ?

目前我使用一个SortedSet<System.Drawing.Point>与自定义IComparer<Point>来存储我的点。当我想知道集合是否包含Point时,我调用BinarySearch。在一个有10000个冲突的集合中,它比HashSet<System.Drawing.Point>.Contains方法快,但它不如HashSet有一个好的哈希值快。

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

您可以创建自己的类来实现IEqualityComparer<Point>,然后将该类交给HashSet构造函数。

的例子:

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());
    }
}