C# suchen in Dictionary mit Klasse als Value

Soma-web

Cadet 4th Year
Registriert
Apr. 2009
Beiträge
86
Hi CB User,
ich muss eine Sensorverwaltung schreiben und habe mir gedacht, dass die ich Sensoren in einem Dictionary<int, KLASSE> verwalte.

Ich möchte aber jetzt den KEY Wert zurückbekommen wenn ich nach einem Value suche.
da Value aber kein normaler Wert ist sondern eben eine Klasse krieg ich das nicht hin.
So wollte ich eigtl suchen:

Code:
 Node newNode = new Node();
            newNode.MID = MID;
            if(network.ContainsValue(newNode.MID)
            {

            }
Das will er aber so nicht :-D

Die Klasse Node (hier sind alle relevanten Daten eines Sensors gespeichert) sieht folgendermaßen aus:

Code:
 class Node
    {
        private int Position;
        private int Devid;
        private string Mid;
        private string Comment;

        public Node()
        {        
        }

        public int POSITION
        {
            get { return POSITION; }
            set { POSITION = value; }
        }

        public int DevID
        {
            get { return DevID; }
            set { DevID = value; }
        }

        public string MID
        {
            get { return Mid; }
            set { Mid = value; }
        }

        public string COMMENT
        {
            get { return Comment; }
            set { Comment = value; }
        }
    }

Und so stelle ich mir das Dictionary vor:
Code:
Dictionary<int, Node> network;


        public Network()
        {       
            network = new Dictionary<int, Node>();
            
         }

Mein Problem ist wie gesagt, dass ich jetzt nach einem bestimmten Value suchen will und dann den Key zurück bekomme?

Wäre sehr dankbar für Tipps/Tricks und Links.

Muss ich jetzt den umweg über KeyValuePair machen und "manuell" suchen?

Danke euch
Grüße Soma
 
Hi,

ein Dict in C# ist "One Way", das heisst die Indizierung funktioniert nur in eine Richtung.

Siehe hier. Da sind aber auch Lösungsvorschläge dabei.

VG,
Mad
 
1.) Im Normalfall hast du bei einem Dictionary den Key und suchst nach dem Value. Wenn du erst mit ContainsValue überprüfen musst, ob der Value vorhanden ist, dann hast du wahrscheinlich einen Fehler in deiner Überlegung.
Der Key eines Dictionary muss eindeutig sein, der Value jedoch nicht. Es ist auch nicht verboten als Key eine Variable der Klasse des Values herzunehmen, die eindeutig ist.

2.) Um in einem Dictionary nach einem Key/Value zu suchen, muss die Klasse (Key bzw. Value) das Interface ICompareable(Of T) implementieren. Erst dann ist es dem Dictionary möglich festzustellen, welche der zwei Klassen denn kleiner bzw. größer ist und wie er sie deshalb einsortieren kann.

Edit: Doch es ist sehr wohl möglich, den umgekehrten Weg zu gehen und den Key auf Grund des Values zu suchen. Man macht es nur normalerweise nicht.
 
Zuletzt bearbeitet:
BÄM seid ihr schnell. DANKE
Ich schaus mir mal an!
Ergänzung ()

Erstmal vielen Dank,
bei meinem Programm ist es nur für ausnahmefälle gedacht den Key anhand der Value zu finden.
Ich gehe jetzt den Umweg und werde es folgendermaßen lösen:
Code:
  public int getPOSITION_byMID(string MID)
        {           
            foreach (KeyValuePair<int, Node> kvp in network)
            {
                if(kvp.Value.MID.Equals(MID))
                {
                    return kvp.Key;
                }
            }
            return 255;
        }

Oder bin ich falsch unterwegs?

Grüße Soma
 
Zuletzt bearbeitet:
andr_gin schrieb:
2.) Um in einem Dictionary nach einem Key/Value zu suchen, muss die Klasse (Key bzw. Value) das Interface ICompareable(Of T) implementieren. Erst dann ist es dem Dictionary möglich festzustellen, welche der zwei Klassen denn kleiner bzw. größer ist und wie er sie deshalb einsortieren kann.

Das ist nicht korrekt. Dictionary macht keine Sortierung beim Einfügen. Hier reicht es wenn man Equals und GetHashCode überschreibt, da das Dicitonary intern eine Hashtable zum einfügen benutzt.

Auszug aus der MSDN:Dictionary<TKey,TValue>
...Dictionary<TKey, TValue> erfordert eine Gleichheitsimplementierung, um zu bestimmen, ob Schlüssel gleich sind. Sie können mithilfe eines Konstruktors, der einen comparer-Parameter akzeptiert, eine Implementierung der generischen IEqualityComparer<T>-Schnittstelle angeben. Andernfalls wird der generische Standardgleichheitsvergleich EqualityComparer<T>.Default verwendet. Wenn der Typ TKey die generische System.IEquatable<T>-Schnittstelle implementiert, verwendet der Standardgleichheitsvergleich diese Implementierung....
Ergänzung ()

@Soma-web: Selbst wenn du nur in Ausnahmefällen nach dem Key suchen musst, ist bei deiner Wahl des Keys ein Fehler unterlaufen, denn nicht die Value wird zum suchen genutzt sondern der Key, das Dicitonary ist darauf optimiert mit dem Key zu suchen. Du solltest die Wahl des Keys eventuell nochmal überdenke ?;)
 
Jetzt mal eine dumme Frage, aber wenn ich wirklich öfters sowohl nach DevID als auch nach Position suchen muss, mach ich dann einfach 2 Dictionarys auf mit dem jeweiligen Key?

"Macht man das so?"

Danke euch!

grüße Soma
 
Hmm jetzt pauschal würde ich sagen bleib bei deinem Dicitonary. Dort hast du ja ne Keys-Property in welcher du auch suchen kannst. Mir fällt aber auch keine bessere Datenstruktur für den Moment ein.
 
Ich erstell jetzt in meiner network Verwaltungsklasse 2 Dictionarys mit Position und DevID als key. Funktioniert einwandfrei.
Das einzige was mich daran stört ist, dass doppelter Platz verbraucht wird. Aber bei 64 Elementen ist das ja kein Problem ;)

Danke euch.
Eine schöne Woche!

Grüße Soma
 
ist zwar Off Topic aber du solltest mal deine Getter und Setter überprüfen.

Nicht dass du dich irgendwann wunderst dass deine private Variablen falsche Werte haben.

Gruß
Hamml
 
@hamml123
Du meinst devid und position oder?
Hab ich schon geändert. hab ich vorgestern Nacht geschrieben, war anscheinend schon einbisschen zu spät ;)

Trotzdem danke
Ergänzung ()

Shit mir is gerade beim Debuggen etwas aufgefallen, hat bestimmt was mit dem alten Problem mit CallByReference oder CallByValue zu tun, aber wenn ich mit der folgenen Methode eine Node meinem Dictionary hinzufügen will, dann überschreit mir diese alle Values in meinem Dictionary. Kann mir bitte jemand meinen Fehler sagen?

Code:
namespace HardRock
{
    /// <summary>
    /// Diese Klasse stellt eine Node dar.
    /// </summary>
    public partial class Node : Form
    {
        private int Position;
        private int Devid;
        private string Mid;
        private string Comment;

        public Node()
        {
            this.Position = 0;
            this.Devid = 0;
            this.Mid = "";
            this.Comment = "";
        }

        public Node(int pos, int dev)
        {
            this.Position = pos;
            this.Devid = dev;
            this.Mid = "";
            this.Comment = "";
        }

        public Node(int pos, int dev, string mid)
        {
            this.Position = pos;
            this.Devid = dev;
            this.Mid = mid;
            this.Comment = "";
        }

        public Node(int pos, int dev, string mid, string com)
        {
            this.Position = pos;
            this.Devid = dev;
            this.Mid = mid;
            this.Comment = com;
        }

        public int POSITION
        {
            get { return Position; }
            set { Position = value; }
        }

        public int DevID
        {
            get { return Devid; }
            set { Devid = value; }
        }

        public string MID
        {
            get { return Mid; }
            set { Mid = value; }
        }

        public string COMMENT
        {
            get { return Comment; }
            set { Comment = value; }
        }
    }
}

die Dict verwaltung/hinzufügen liegt in der Klasse Network:

Code:
 public bool addNode(Node node)
        {
            if (network.ContainsKey(node.DevID) || networkbypos.ContainsKey(node.POSITION))
            {
                switch (MessageBox.Show(
                    "Sensor " + node.DevID + 
                    " already exists. \r\nDo you want to replace it?",
                    "Replace?",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question))
                {
                    case DialogResult.Yes:
                        network.Remove(node.DevID);
                        networkbypos.Remove(node.POSITION);
                        network.Add(node.DevID, node);
                        network.Add(node.POSITION, node);
                        FreeDevID.Remove(node.DevID);
                        return true;
                    case DialogResult.No:
                        return false;
                }
            }
            network.Add(node.DevID, node);
            networkbypos.Add(node.POSITION, node);
            FreeDevID.Remove(node.POSITION);            
            return true;
        }

In der main ruf ich die dann folgendermaßen auf

Code:
Node newnode = new Node(1,2)
network.addNode(newnode);

Wenn ich jetzt danach eine neue Node(3,2) hinzufügen will
haben beide Noden den Value 3,2 in meinem Dict.

Wie kann ich das Problem umgehen?
muss ich jetzt immer ne neue Instanz Node erstellen? also immer eine neue?
Irgendwo überschreibt er mir den Value?Heißt das dass was bei meiner Klasse Node nicht stimmt?
Ds Dict zielt anscheinend immer auf den selben arbeitsbereich, wieso?
*EDIT*
Ich habs ich hab bei der schleife in der ich addNode() aufrufe immer die selbe Node neu gefüllt und keine neue erstellt, kein Wunder.

Sobald ich es geschreiben hatte, hatte ich es!!!

DANKE EUCH!?
 
Zuletzt bearbeitet:

Ähnliche Themen

Zurück
Oben