Zum Inhalt springen

Dictionaries in Listen packen und danach auf die Dictionaries zugreifen


Gewinde

Empfohlene Beiträge

Hallo zusammen,

ich würde für mein Übungsprojekt gerne ein Dictionary<Type , int> erstellen und dieses dann in einer anderen Klasse als Erweiterung für diverse Variablen nutzen. Das Problem ensteht dabei, sobald ich ein weiteres Objekt in das Dictionary geben möchte. Da es sich hierbei um den gleichen Typen handelt, wird die Speicherung aufgrund der Eindeutigkeit der Schlüssel abgelehnt. Der Compiler meckert, da dieser Schlüssel (Type) schon vorhanden ist. Jetzt wurde mir der Tip gegeben, nach dem Erstellen des Dictionary dieses in eine Liste zu speichern. Da eine Liste Objekte des selben Typs speichern kann, wäre das Problem mit dem Compiler gelöst. Es würde also eine Liste mit vielen Dictionaries entstehen, wobei jedes Dictionary nur 1 Typen beherbergen würde. Bis zu diesem Schritt komme ich auch noch problemlos mit. Dictionary erstellen, Dictionary in die Liste legen fertig.

Das Problem beginnt, sobald ich nun versuche in der Klasse in welcher sich nun die Liste befindet, auf die Daten der jeweiligen Dictionaries zuzugreifen. Meine Idee war es, mittels foreach-Schleife die Liste zu durchlaufen um dann für jeden Typen in einer weiteren Schleife an den kvp.value heranzukommen. Als Alternative habe ich es mit einer for-Schleife versucht. In beiden Fällen wird mir der Zugriff auf die Werte verweigert.

Hat jemand eventuell einen Zaunpfahl für mich, wie ich dieses Problem lösen könnte?

mit freundlichem Gruß

Gewinde 🙂

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kannst du vielleicht das konkrete Problem beschreiben? Ich verstehe nicht, wieso wozu du mehrfach den selben Key in das Dictionary schreiben möchtest. Ein Dictionary ist nun mal ein Schlüssel-Wert-Paar, wobei ein Schlüssel eindeutig sein muss.

Wenn du mehrere Integer-Werte pro Typ ablegen möchtest, könntest du den Wert auch immer addieren oder du machst ein Dictionary<Type, List<int>>

Link zu diesem Kommentar
Auf anderen Seiten teilen

Yo müsstest dein Code hier posten um zu sehen wo dein Fehler ist.

Probiere mal folgendes mit KVP:

List<KeyValuePair<Type, int>> kvpListe = new List<KeyValuePair<Type, int>>();
var kvpEintrag = new KeyValuePair<Type, int>(null, 0);
kvpListe.Add(kvpEintrag);
kvpListe.Add(new KeyValuePair<Type, int>(typeof(object), 1));
kvpListe.Add(new KeyValuePair<Type, int>(typeof(string), 2));

oder mit Tupel:

List<Tuple<Type, int>> tupelListe = new List<Tuple<Type, int>>();
var tupelEintrag = new Tuple<Type, int>(typeof(int), 1);
tupelListe.Add(new Tuple<Type, int>(typeof(int), 1));
tupelListe.Add(tupelEintrag);
tupelListe.Add(new Tuple<Type, int>(typeof(byte), 2));

oder eine eigene generische Klasse:

    class MeinWoerterbuchGenerisch<TSchluessel, TWert>
    {
        private Dictionary<TSchluessel, TWert> _wbuch = new Dictionary<TSchluessel, TWert>();

        public MeinWoerterbuchGenerisch() {}
        public MeinWoerterbuchGenerisch(TSchluessel s, TWert w)
        {
            _wbuch.Add(s,w);
        }
        public void Add(TSchluessel s, TWert w) 
        {
            _wbuch.Add(s, w);
        }
    }
MeinWoerterbuchGenerisch<object, int> mWBuch = new MeinWoerterbuchGenerisch<object, int>();
mWBuch.Add(typeof(object), 1);
mWBuch.Add(typeof(int), 2);

 

Bearbeitet von ihkaka
Link zu diesem Kommentar
Auf anderen Seiten teilen

Man könnte auch einfach eine Liste von Tuple nehmen und dann mittels ToLookup() oder ein GroupBy() eine Gruppierung daraus machen.

using System.Linq;

//...

List<(Type, int)> list = new ();
list.Add((typeof(string), 5));
list.Add((typeof(string), 10));

// ...

list.GroupBy(x => x.Item1);

Die Elemente vom Tuple kann man auch noch benennen oder man macht gleich daraus ein Record.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • Chief Wiggum änderte den Titel in Dictionaries in Listen packen und danach auf die Dictionaries zugreifen

Hallo zusammen,

das sind einige Zaunpfähle die ihr mir da gegeben habt. Ich werde mir die Tage mal viel Zeit nehmen um mich da durch zuwurschteln. Danke dafür 🙂

Ich versuche mal etwas Code zu zeigen, leider endet dieser bei dem Versuch auf die Daten zuzugreifen.

public abstract class Verstärkung
    {
        protected string _id;
        protected int _wert;
        protected int _maxWert;

        protected Verstärkung(string id , int wert)
        {
            ID = id;
            Wert = wert;
        }

        public string ID { get; set; }
        public int Wert
        {
            get { return _wert; }
            set
            {
                if (value > _maxWert)
                {
                    _wert = _maxWert;
                }
                else _wert = value;
            }
        }

Dies sind die Verstärkungen welche in das Dictionary übergeben werden sollen. Ich hatte diese beim letzten Mal um eine ID erweitert, um diese dann als eindeutigen Schlüssel zu bekommen.

    public class Halterung
    {
        private Dictionary<Verstärkung, int> halterung = new Dictionary<Verstärkung, int>();

        public void NeueHalterung(Verstärkung verstärkung)
        {
            halterung.Add(verstärkung , verstärkung.Wert);
        }
    }

Das Dictionary in dem die Daten an die Liste übergeben werden sollen. Da die Anzahl der Verstärkungen begrenzt werden sollte (es soll später verschiedene Verstärkungen geben z.B. Kinetik , Energie , u.s.w.) lag die idee beim Type als Schlüssel.

 public abstract class Rüstung
    {
        protected int _maxPlätze;
        protected List<Halterung> steckplatz;

        protected int _kinetisch;
        protected int _magisch;

        protected Rüstung(int kinetisch , int magisch)
        {
            Kinetisch = kinetisch;
            Magisch = magisch;
        }

        public int Kinetisch { get; set; }
        public int Magisch { get; set; }
    }

Das sollte die Basisklasse werden, die Liste befindet sich später in der Rüstung und soll dann mit einer Methode befüllt werden. Die Variable _maxPlätze dient später dazu die Größe der Liste zu begrenzen.

  internal class LederRüstung : Rüstung
    {
        public LederRüstung(int kinetisch, int magisch) : base(kinetisch, magisch)
        {
            _maxPlätze = 7;
            steckplatz = new List<Halterung>();
        }

        public void Aufwertung(Halterung halterung)
        {
            if(steckplatz.Count -1 < _maxPlätze)
            {
                steckplatz.Add(halterung);
            }
            else Console.WriteLine("Kein Einbau möglich.");
        }

        //Dieser Code ist falsch, 

        public void Information()
        {
            foreach(KeyValuePair<Type , int>> halterung in steckplatz)
            {
                //Es sollen mittels Schleife z.B. die Dictionarys aus der Liste geholt werden
            }
        }

Ich möchte die KeyValuePair bzw. die Value aus den Dictionaries weiterverwenden, um diese dann mittels Methode auf die jeweiligen Rüstungswerte zu addieren. Wenn der Anwender die Verstärkungen ausbaut, sollen die Werte automatisch von den Rüstungswerten subtrahiert werden (das ist allerdings erstmal noch Zukunftsmusik). Mittels Schleife komme ich zwar an die Type in der Liste heran, jedoch nicht eine Ebene tiefer in die Dictionary.

 

Ich hoffe der Code hilft etwas bei der Erklärung, auch wenn er bestimmt voller Fehler ist. 😄 Die merze ich später aber auch noch aus, versprochen.

grüße Gewinde

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich verstehe nicht, wieso eine Verstärkung Halterung genannt wird und Halterung wiederrum Steckplatz. Man sollte schon beim gleichen Namen bleiben, damit man versteht, was gemeint ist.

Was genau willst du mit dem Dictionary erreichen? Ein Dictionary ist ja dafür gedacht, dass man mit Hilfe eines Schlüssels einen Wert ermitteln kann. Ich sehe nicht, wozu du den Schlüssel benötigst. Also kann es auch eine ganz normale Liste sein.

Am Besten erklärst du das konkrete Problem und zeigst nicht unbedingt dein Code. Außerdem sehe ich da sehr viele Fehler im Code. z.B. sollte deine Methode Aufwertung() keine Konsolenausgabe machen, sondern eine Exception werfen, weil dies nicht erlaubt ist. Stell dir vor, du willst dein Spiel mal mit einer grafischen Oberfläche erweitern. Da kommst du dann mit Konsolenausgaben nicht mehr weit.

Link zu diesem Kommentar
Auf anderen Seiten teilen

So wie ich das sehe erstellst du wohl ein Spiel. Die Rüstung soll verschiedene Arten von Werte haben.

Prinzipiell ist es schon mal gut, dass du eine abstrakte Klasse erstellst, allerdings nutzt du nicht alle Möglichkeiten aus.

Nehmen wir z.B. die Methode Information. Diese hast du in Lederrüstung implementiert. Auch wenn das zu Testzwecken ist, solltest du dich fragen ob das überhaupt sinnvoll ist. Eine Methode um Informationen für ein Item aufzurufen wirst du an vielen Stellen benötigen, es sollte also nicht in jeder Klasse implementiert sein. Es bietet sich also an entsprechende Methode direkt in 'Rüstung' zu verschieben, oder eine Klasse zu schreiben, die verschiedene Meldungen zu einem Item bringt.

Desweiteren solltest du grundlegende Informationen für Items in ein Interface packen. Jedes Item wird einen Namen haben, jedes Item wird evtl. eine ID haben etc.

Auch machst du dir das Leben schwer, wenn du innerhalb der spezifischen Rüstung definierst, welche Werte diese haben kann bzw hat. Du könntest vielmehr diese Werte in einer eigenen Klasse definieren und diese der Lederrüstung übergeben.

So müsstest du nicht viele Klassen bei einer Änderung anpassen.

Deine foreach Schleife sieht auf den ersten Blick falsch aus. Das ist eine Liste der Klasse Halterung. Wenn du auf das Dictionary aus Halterung zugreifen willst, dann darf dieses nicht 'private' sein.

Dein Dictionary passt auch nicht zu <Type, int> sondern ist <Verstärkung, int> ... das ist also grundsätzlich falsch. Es dürfte auch schwierig sein, dieses Dictionary zu durchsuchen, da du das entsprechende 'Verstärkung' Objekt haben müsstest bzw. zuminderst die ID wissen müsstest um dieses in den Keys zu identifizieren.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum überhaupt abstrakte Klasse Verstärkung, wenn du in Halterung ein Objekt vom Typ Verstärkung erwartest ?Dictionary<Verstärkung, int> sollte eine Liste von Verstärkungen sein List<Verstärkung>, oder wieso ist der int Wert überhaupt da wenn Verstärkung schon den Wert enthält ?

Naja wenn es sich nur um die reine Ausgabe geht, dann sollten folgende Änderungen es fixen:

public class Verstärkung // Änderung, weil in Halterung als Objekt erwartet und deswegen kann nicht abstract sein
{
    protected string _id;
    protected int _wert;
    protected int _maxWert = 19; //Änderung, weil sonst immer "0" wegen Abfrage in set-Block unten
    public Verstärkung(string id, int wert)
    {
        ID = id;
        Wert = wert;
    }
    public string ID { get; set; }
    public int Wert
    {
        get { return _wert; }
        set
        {
            if (value > _maxWert)
            {
                _wert = _maxWert;
            }
            else _wert = value;
        }
    }
}
public class Halterung
{
    protected Dictionary<Verstärkung, int> halterung = new Dictionary<Verstärkung, int>();
    public void NeueHalterung(Verstärkung verstärkung)
    {
        halterung.Add(verstärkung, verstärkung.Wert);
    }
    public IReadOnlyDictionary<Verstärkung, int> GetHalterung() //Lese-Zugriff für Ausgabe
    {
        return halterung;
    }
}
internal class LederRüstung : Rüstung
{
    public LederRüstung(int kinetisch, int magisch) : base(kinetisch, magisch)
    {
        _maxPlätze = 7;
        steckplatz = new List<Halterung>();
    }
    public void Aufwertung(Halterung halterung)
    {
        if (steckplatz.Count - 1 < _maxPlätze)
        {
            steckplatz.Add(halterung);
        }
        else Console.WriteLine("Kein Einbau möglich.");
    }
    public void Information()
    {
        foreach (var halterung in steckplatz)
        {
            foreach (var kvpElement in halterung.GetHalterung())
            {
                Console.WriteLine("Verstärk-ID:{0}, Verstärk-Wert:{1}, Halterung-Platz:{2}", kvpElement.Key.ID, kvpElement.Key.Wert, steckplatz.IndexOf(halterung)+1);
            }
        }
    }
}

 

Dann das Ganze nutzen wie folgt:

LederRüstung lr = new LederRüstung(10, 110);

Halterung h = new Halterung();
Halterung h2 = new Halterung();

h.NeueHalterung(new Verstärkung("Kupferösen", 8));
lr.Aufwertung(h);

h2.NeueHalterung(new Verstärkung("Zaubergarn-Hexenstich", 2));
lr.Aufwertung(h2);

lr.Information();

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Abend zusammen,

KeeperOfCoffee hat recht. Es sollen später viele verschiedene Verstärkungen zur Verfügung stehen. Bei den einzelnen Rüstungen versuche ich auch 3-5 verschiedene zu implementieren, jede mit anderen Vorteilen und Schwächen. Ich habe in meinem neuen Code auch implementiert, dass die Werte der einzelnen Objekte automatisch ansteigen, sobald man das Level des Objekts erhöht. Ich werde alle eure Tipps stück für stück verarbeiten und daraus lernen. Mein Problem wurde auf jeden Fall gelöst. Wie schon gesagt, bis vor kurzem dachte ich, dass es nur Dictionary<keyvaluepair> oder aber List<xyz> gibt. Das mit der List<keyvaluepair> oder den Tuple wird in meinen Büchern leider nicht erwähnt. Damit ist das Problem des eindeutigen Schlüssels nicht mehr vorhanden. Wäre schön wenn so etwas wenigstens mal kurz angesprochen werden würde in den Büchern. 🤔

Ich habe jetzt ein List<keyvaluepair<Type,float>> implementiert. Wenn ich wieder etwas mehr Zeit habe werde ich versuchen die Klassen noch etwas besser zu gestallten. Ein übergeordnetes Interface , dann die abstracten Klassen und danach die Kindklassen u.s.w..

Mal sehen, da steckt noch viel Arbeit vor mir. Ich freu mich drauf 🙂

Danke euch allen 👍

Gruß Gewinde

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...