2015-05-26 7 views
6

System.Drawing.Point hat eine wirklich, wirklich schlecht GetHashCode Methode, wenn Sie beabsichtigen, es zu verwenden, um beschreibt ‚Pixel‘ in einem Bild/Bitmap: it is just XOR between the X and Y coordinates.Stellvertreter die GetHashCode() Methode der System.Drawing.Point

Also für ein Bild mit sagen wir mal 2000x2000 Größe, hat es eine absurde Anzahl von Kolonien, da nur die Zahlen in der Diagonale einen anständigen Hashwert haben werden.

Es ist ziemlich einfach, eine anständige GetHashCode Methode mit ungeprüfter Multiplikation zu erstellen, wie einige Leute bereits erwähnt here.

Aber was kann ich tun, um diese verbesserte GetHashCode Methode in einem HashSet zu verwenden? Ich weiß, ich könnte meine eigene Klasse/Struktur MyPoint erstellen und implementieren Sie mit dieser verbesserten Methoden, aber dann würde ich alle anderen Teile des Codes in meinem Projekt, die eine System.Drawing.Point verwenden.

Ist es möglich, die Methode von System.Drawing.Point mit einer Art von Extension-Methode oder dergleichen zu "überschreiben"? Oder die HashSet "zu sagen", eine andere Funktion anstelle der GetHashCode zu verwenden?

Momentan verwende ich eine SortedSet<System.Drawing.Point> mit einer benutzerdefinierten IComparer<Point>, um meine Punkte zu speichern. Wenn ich wissen will, ob das Set einen Punkt enthält, rufe ich BinarySearch an. Es ist schneller als eine HashSet<System.Drawing.Point>.Contains Methode in einem Set mit 10000 Kolonien, aber es ist nicht so schnell wie HashSet mit einem guten Hash könnte sein.

Antwort

10

Sie können Ihre eigene Klasse erstellen, die IEqualityComparer<Point> implementiert, und dann diese Klasse an die HashSet constructor übergeben.

Beispiel:

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

Das ist genial! Ich habe nicht bemerkt, dass ein IEqualityComparer eine GetHashCode() -Methode hatte! Perfekte Antwort! – Trauer

Verwandte Themen