Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Generic.SortedList - Frage
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

Generic.SortedList - Frage

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers
feadur
myCSharp.de - Member



Dabei seit:
Beiträge: 726
Herkunft: Bonn

beantworten | zitieren | melden

hi,
ich vermisse grad sowas wie

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

das hast du aber gemacht, oder? =)
private Nachricht | Beiträge des Benutzers
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

beantworten | zitieren | melden

Zitat
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...
private Nachricht | Beiträge des Benutzers
EvilTK
myCSharp.de - Member



Dabei seit:
Beiträge: 265

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

beantworten | zitieren | melden

Zitat
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?
Zitat
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...
private Nachricht | Beiträge des Benutzers
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers
EvilTK
myCSharp.de - Member



Dabei seit:
Beiträge: 265

beantworten | zitieren | melden

Zitat
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.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo EvilTK,
Zitat
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,
Zitat
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.
Zitat
SortedList stellt eine Auflistung von Schlüssel-Wert-Paaren dar, die auf Grundlage der zugeordneten IComparer-Implementierung nach den Schlüsseln sortiert sind.
herbivore
private Nachricht | Beiträge des Benutzers
maxE
myCSharp.de - Member



Dabei seit:
Beiträge: 456
Herkunft: Sachsen

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
EvilTK
myCSharp.de - Member



Dabei seit:
Beiträge: 265

beantworten | zitieren | melden

Zitat
Original von herbivore
Hallo EvilTK,
Zitat
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 :D)
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo EvilTK,

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

herbivore
private Nachricht | Beiträge des Benutzers
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

beantworten | zitieren | melden

Zitat
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.
Zitat
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...
private Nachricht | Beiträge des Benutzers
Thommi
myCSharp.de - Member



Dabei seit:
Beiträge: 34

Themenstarter:

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers