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

Substitute the GetHashCode() Method of System.Drawing.Point

System.Drawing.Point 有一个非常非常糟糕的 GetHashCode 方法,如果你打算用它来描述 Image/Bitmap 中的 'pixels':it is just XOR between the X and Y coordinates.

因此,对于尺寸为 2000x2000 的图像,它具有荒谬的碰撞次数,因为只有对角线中的数字才会具有合适的哈希值。

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

但是如何在 HashSet 中使用这个改进的 GetHashCode 方法? 我知道我可以创建自己的 class/struct MyPoint 并使用这种改进的方法来实现它,但是我会破坏项目中使用 System.Drawing.Point.[= 的所有其他代码片段28=]

是否可以使用某种扩展方法或类似方法 "overwrite" 来自 System.Drawing.Point 的方法?还是要"tell" HashSet 使用另一个函数代替GetHashCode?

目前我正在使用带有自定义 IComparer<Point>SortedSet<System.Drawing.Point> 来存储我的积分。当我想知道集合是否包含点时,我调用 BinarySearch。它比具有 10000 次碰撞的集合中的 HashSet<System.Drawing.Point>.Contains 方法更快,但它不如具有良好哈希的 HashSet 快。

您可以创建自己的 class 来实现 IEqualityComparer<Point>, then give that class to the 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());
    }
}