Zum Inhalt springen

Dictionaries in Listen packen und danach auf die Dictionaries zugreifen


Empfohlene BeitrÀge

Geschrieben

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 🙂

Geschrieben

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>>

Geschrieben (bearbeitet)

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
Geschrieben

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.

Geschrieben
vor 41 Minuten schrieb Whiz-zarD:
List<(Type, int)> list = new ();

Ah schön C# 9+, muss auch mal hoch Leveln 😀;

Ich denke er versucht einen Zugriff auf seine Liste von WörterbĂŒchern ohne Indexer, naja mal schauen ob er seinen Code postet.

  • Thanks-and-Goodbye Ă€nderte den Titel in Dictionaries in Listen packen und danach auf die Dictionaries zugreifen
Geschrieben

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

Geschrieben

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.

Geschrieben

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.

Geschrieben

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();

 

Geschrieben

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

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...