Laden...

Generic.SortedList - Frage

Erstellt von Thommi vor 17 Jahren Letzter Beitrag vor 17 Jahren 3.409 Views
T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren
Generic.SortedList - Frage

Moin Leute,

Ich habe folgende Liste:

        SortedList<myType,int> myList = new SortedList<myType,int>();

myType ist eine eigene Klasse, die 5 int-Properties hat, die im Konstruktor übergeben werden:

        
class myType: IComparable<myType>,IEquatable<myType>
    {
        public myType(int val1, int val2, int val3, int val4, int val5)

        public int  CompareTo(myType other)
        {
            // per Default ungleich
            int result = -1;

            // nur gleich, wenn alles übereinstimmt
            if (
                this.val1 == other.val1 &&
                this.val2 == other.val2 &&
                this.val3 == other.val3 &&
                this.val4 == other.val4 &&
                this.val5 == other.val5)
                result = 0;

            return (result);
        }
}

Die Liste wird mit vielen Key-Value- Paaren, die alle den Wert "0" haben, initialisiert.

Im weiteren Verlauf komme ich in Schleifen, in denen der Wert für bestimmte Keys auf "1" gesetzt wird. Oder besser gesagt: gesetzt werden soll, denn das funktioniert nicht.

Mal geht es, mal nicht 🤔

Wenn es nicht geht, wird ein neuer Wert am Ende der Liste eingefügt, so daß ich dann zwei Items mit dem gleichen Key habe. Äh... kann doch gar nicht sein 8o ?!?!?

Aber wenn ich in die Watchlist gucke, ist dort zweimal der gleich Key, also zumindest sehe ich keinen Unterschied.

Was mach ich falsch? Hat jemand eine Idee? Bestimmt hab ich grad ein ganz großes Brett vor'm Kopf...

Nichts ist, wie es scheint...

F
722 Beiträge seit 2005
vor 17 Jahren

hi,
ich vermisse grad sowas wie

public int Val1
{
get {return val1;}
set {val1 = value;}
}
 

das hast du aber gemacht, oder? =)

T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren

Original von feadur
das hast du aber gemacht, oder? =)

Ja, ist natürlich drin. Sind auch noch mehr Methoden drin, z.B. Equals(), sonst würde es ja die IEquatable nicht einbinden. Ich wollte nur die Zitate nicht so aufblähen.

Nichts ist, wie es scheint...

E
265 Beiträge seit 2004
vor 17 Jahren

ToCompare sollte -1 für kleiner, 0 für gleich und 1 für großer zurückgeben.

Gleicher Key, ... hast du die GetHasCode Methode richtig implementiert?

T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren

Original von EvilTK
ToCompare sollte -1 für kleiner, 0 für gleich und 1 für großer zurückgeben.

Da mich nur die Gleichheit interessiert, ist nur das implementiert. "Größer" bzw "Kleiner" läßt sich auch logisch nicht so recht definieren. Meinst Du, das kann man so nicht machen?

Original von EvilTK
Gleicher Key, ... hast du die GetHasCode Methode richtig implementiert?

🙁 Hm, die kenn ich gar nicht. Erst mal gucken geh, was das ist...

Nichts ist, wie es scheint...

T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren

So, nochmal ich.

Sehe ich folgendes richtig:

In die SortedList werden quasi-doppelte Keys eingetragen und vorhandene Keys nicht wiedergefunden, weil die in myType von mir überschriebene Equals()-Methode irgendwie schiefläuft?

Die Methode sieht folgendermaßen aus:


public bool Equals(myType other)
        {
            bool result = false;

            if (
                this.val1 == other.val1 &&
                this.val2 == other.val2 &&
                this.val3 == other.val3 &&
                this.val4 == other.val4 &&
                this.val5 == other.val5)
                result = true;

            return (result);
        }

Kann jemand den Fehler sehen?

Nichts ist, wie es scheint...

E
265 Beiträge seit 2004
vor 17 Jahren

MSDN
The objects used as keys by a Hashtable are required to override the Object.GetHashCode method (or the IHashCodeProvider interface) and the Object.Equals method (or the IComparer interface). The implementation of both methods and interfaces must handle case sensitivity the same way; otherwise, the Hashtable might behave incorrectly.

SortedList, List, etc. verwenden intern alle die Hashtable logik oder sogar ne hashtable, kann man sich ja mit reflector anschauen.

Es wird neben der Equals methode auch der HasCode eines objektes überprüft.
Wenn man die GetHashCode Methode nicht überschreibt gibt diese den Pointer des objektes zurück. Und jedes objekt das mit new erzeugt wurde hat einen anderen Pointer -> anderen HasCode, du wirst also nie einen doppelten key erzeugen können.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo EvilTK,

SortedList, List, etc. verwenden intern alle die Hashtable logik oder sogar ne hashtable, kann man sich ja mit reflector anschauen.

das halte ich für ein Gerücht. Für SortedList benutzt m.E. die GetHashCode-Methode nicht, weshalb der Fehler damit auch nicht zusammenhängen kann.

Hallo Thommi,

In die SortedList werden quasi-doppelte Keys eingetragen und vorhandene Keys nicht wiedergefunden, weil die in myType von mir überschriebene Equals()-Methode irgendwie schiefläuft?

Die Equals-Methode interessiert SortedList wohl auch nicht.

SortedList stellt eine Auflistung von Schlüssel-Wert-Paaren dar, die auf Grundlage der zugeordneten IComparer-Implementierung nach den Schlüsseln sortiert sind.

herbivore

M
456 Beiträge seit 2004
vor 17 Jahren

Für die SortedList implementiert man am besten ein IComparer oder IComparable Interface. Und warum kaskadierst du die if-Bedingungen in der Vergleichsmethode nicht? Das sollte IMHO besser gehen:

public int CompareTo(myType other)
{
    if (this.val1 < other.val1)
        return -1;
    else if (this.val1 > other.val1)
        return 1;
    else
        if (this.val2 < other.val2)
            return -1;
        else if (this.val2 > other.val2)
            return 1;
        else
           // ... für alle Werte bis val5 
              if (this.val5 < other.val5)
                  return -1;
              else  if (this.val5 > other.val5)
                  return 1;
              else
                  return 0; // alle sind gleich

        }

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo maxE,

durch Verwendung von return, kann und sollte man sich die "elseses" und die Einrückungen sparen:


public int CompareTo(myType other)
{
    if (this.val1 < other.val1) { return -1; }
    if (this.val1 > other.val1) { return  1; }
    //...
    if (this.val5 < other.val5) { return -1; }
    if (this.val5 > other.val5) { return  1; }
    return 0; // alle sind gleich
}

herbivore

E
265 Beiträge seit 2004
vor 17 Jahren

Original von herbivore
Hallo EvilTK,

SortedList, List, etc. verwenden intern alle die Hashtable logik oder sogar ne hashtable, kann man sich ja mit reflector anschauen.
das halte ich für ein Gerücht. Für SortedList benutzt m.E. die GetHashCode-Methode nicht, weshalb der Fehler damit auch nicht zusammenhängen kann.

Zu schnell geschossen. Sorry für die falsche erklärung.
Aber bei einem Dictionary bin ich mir sicher das die GetHasCode Methode verwendet wird. (hoffentlich ist das jetzt auch nicht falsch sonst endet das peinlich 😄)

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo EvilTK,

ich kann dich beruhigen. Ein Dictionary ist nichts weiter als eine typsichere Hashtable. Deshalb wird GetHashCode von Dictionary benötigt.

herbivore

T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren

Original von herbivore
Für SortedList benutzt m.E. die GetHashCode-Methode nicht, weshalb der Fehler damit auch nicht zusammenhängen kann.

Zumindest hat sich nach Implementierung einer GetHashCode-Methode nichts verändert 😉 Das spricht für Dich.

Original von herbivore
SortedList stellt eine Auflistung von Schlüssel-Wert-Paaren dar, die auf Grundlage der zugeordneten IComparer-Implementierung nach den Schlüsseln sortiert sind.

IComparer ist ja in myType drin, siehe mein Ausgangsposting. Ich hatte allerdings den größer/kleiner-Teil "weggelassen", weil mir nicht klar war, nach welchen Kriterien ich das in diesem konkreten Fall entscheide und ich nicht gesehen habe, wozu es notwendig wäre.
Wenn aber die SortedList nur mit vollständig ausformulierter CompareTo-Methode des Key-Typs funktioniert, werde ich mir wohl morgen was einfallen lassen müssen.
Um erst mal weiterarbeiten zu können, hatte ich heute den Key-Typ in string geändert, aber das Umwandeln von myType in einen string nimmt einiges an Performance weg und begeistert mich nicht so sehr...

Nichts ist, wie es scheint...

T
Thommi Themenstarter:in
34 Beiträge seit 2006
vor 17 Jahren

Zum Abschließen dieses Threads:

Problem gelöst - die vollständige Implementierung von CompareTo() ermöglicht die korrekte Sortierung / das Wiederfinden der Keys.

Wieder was gelernt 🙂

Danke herbivore!

Nichts ist, wie es scheint...