Laden...

Werte in Listen haben alle selbe Einträge

Erstellt von der-gee vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.392 Views
D
der-gee Themenstarter:in
4 Beiträge seit 2015
vor 9 Jahren
Werte in Listen haben alle selbe Einträge

Hallo zusammen,

ich hoffe mit dem Beitrag gegen keine Foren Regel zu verstoßen 😃

Ich möchte *.sol Dateien einlesen, diese Parsen und dann entsprechend in XML oder CSV auswerfen. Dafür habe ich ein eigenen "Typ" erstellt, der folgendermaßen aussieht:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParseSOL
{
    class loggedActivity
    {
        private string nameEntity;
        private int runTime;
        private int amountCalls;

        public string NameEntity
        {        
            get { return nameEntity; }
            set { nameEntity = value; }
        }

        public int RunTime
        {
            get { return runTime; }
            set { runTime = value; }
        }

        public int AmaountCalls
        {
            get { return amountCalls; }
            set { amountCalls = value; }
        }
    }

    class errorCase
    {
        private string errorName;
        private int startTime;
        private int endTime;
        public List<loggedActivity> Actions = new List<loggedActivity>();

        public string ErrorName
        {
            get { return errorName; }
            set { errorName = value; }
        }

        public int StartTime
        {
            get { return startTime; }
            set { startTime = value; }
        }
        public int EndTime
        {
            get { return endTime; }
            set { endTime = value; }
        }
    }
}

Diesen Typ möchte ich befüllen, indem ich eben eine *.sol Datei entsprechend Parse. Bisher habe ich eine List<string>, welche unerwünschten Zeichen und Zeilen befreit ist. Diese gebe ich Häppchenweise an meine Füllfunktion. Nur spuckt mir diese pro Aufruf eine Liste mit jeweils gleichen Werten zurück.

Es scheint mir, dass ich statt Wert-Zuweisungen immer nur Referenzen setzte, sodass pro Aufruf am Ende immer alle jeweiligen Listeneinträge auf die jeweils gleiche Variable zeigen.

Abgekürzt kann mein Problem mit folgedem Code reproduziert werden:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ParseSOL
{
    class ParseSOL
    {
        static void Main(string[] args)
        {			
            loggedActivity act = new loggedActivity();
            act.AmaountCalls = 1;
            act.RunTime = 2;
            act.NameEntity = "Hallo";

            // Werte der Liste hinzufügen
            List<loggedActivity> narf = new List<loggedActivity>();
            narf.Add(act);

            // Neue Werte und nochmals der Liste hinzufügen
            act.NameEntity = "Ciao";
            act.AmaountCalls = 3;
            act.RunTime = 4;
            narf.Add(act);

            // Die Liste mit Werten an dem entsprechendem Typ hinzufügen
            errorCase err = new errorCase();
            err.Actions = narf;
            err.StartTime = 0;
            err.EndTime = 1;
            err.ErrorName = "Error 1";

            List<errorCase> errList = new List<errorCase>();
            errList.Add(err);
            errList.Add(err);

            for (int i = 0; i < errList.Count; i++)
            {
                Console.WriteLine("Error Name: " + errList[i].ErrorName);
                for (int j = 0; j < errList[i].Actions.Count; j++)
                {
                    Console.WriteLine("Name  : " + errList[i].Actions[j].NameEntity);
                    Console.WriteLine("Calls : " + errList[i].Actions[j].AmaountCalls);
                    Console.WriteLine("Time  : " + errList[i].Actions[j].RunTime);
                }
            }
            System.Console.ReadLine();            
        }
    }
}

Ich wünschte, die Ausgabe würde so aussehen:

Error Name: Error 1
Name  : Hallo
Calls : 1
Time  : 2
Name  : Ciao
Calls : 3
Time  : 4
Error Name: Error 1
Name  : Hallo
Calls : 1
Time  : 2
Name  : Ciao
Calls : 3
Time  : 4

Aber das hier ist der Fall:

Error Name: Error 1
Name  : Ciao
Calls : 3
Time  : 4
Name  : Ciao
Calls : 3
Time  : 4
Error Name: Error 1
Name  : Ciao
Calls : 3
Time  : 4
Name  : Ciao
Calls : 3
Time  : 4

Ich "überschreibe" absichtlich die Variable act.*, da dies auch in meinen Funktionen so gemacht wird, da diese sonst gewaltig aufgeblasen und unübersichtlich wären.

Kann mir bitte jemand sagen, wo ich mich rattendämlich anstelle und wie es richtig aussehen muss? Damit wäre mir Wahnsinnig geholfen! Ich vermute, dass ich andauernd Referenzen statt Werten zuweise.

Herzlichen Dank für Eure Hilfe!

2.298 Beiträge seit 2010
vor 9 Jahren

Du darfst die Variable "act" eben nicht überschreiben. - "act" bleibt die Referenz. Nur weil du eine Property änderst wird dies nicht gleich ein neues Objekt.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

D
der-gee Themenstarter:in
4 Beiträge seit 2015
vor 9 Jahren

Doof. In der Funktion welche ich verwende habe ich probehalber versucht, bei jeder Iteration das Objekt (hier stellvertreten durch act) neu zu initialisieren. Das hat dazu geführt, dass mir der Speicher übergelaufen ist 😦 Gibt es einen Kniff, den ich verwenden könnte?

2.207 Beiträge seit 2011
vor 9 Jahren

Wieviele Objekte machst du denn? Bist du sicher, dass du richtig iterierst?

Gruss

Coffeebean

D
der-gee Themenstarter:in
4 Beiträge seit 2015
vor 9 Jahren

Du darfst die Variable "act" eben nicht überschreiben. - "act" bleibt die Referenz. Nur weil du eine Property änderst wird dies nicht gleich ein neues Objekt.

Wieviele Objekte machst du denn? Bist du sicher, dass du richtig iterierst?

Ich muss wohl eben in der Iteration einen Fehler haben. Bei einer Liste mit 80 Strings wirft er mir die "System.OutOfMemoryException". Der Laufindex beträgt 12013057 >.<

Mal sehen, was passiert, sobald ich den Fehler behoben habe. Erstmal vielen Dank für Eure Hilfe und ich halte Euch auf dem Laufenden!

Schöne Grüße,
der-gee

2.207 Beiträge seit 2011
vor 9 Jahren

[Hinweis] Wie poste ich richtig? 2.3 Kein Full Quotes

Schau dir mal Werttypen und Referenztypen an. Für dein act-Objekt und den Ausganspunkt dieses Threads.

Mit dem [Artikel] Debugger: Wie verwende ich den von Visual Studio? findest du schnell heraus, warum er mehr als 12 Mio mal duch deine Schleife rennt 😉

Gruss

Coffeebean

C
224 Beiträge seit 2009
vor 9 Jahren

Tipp:


//statt
for (int i = 0; i < errList.Count; i++)
{
   Console.WriteLine("Error Name: " + errList[i].ErrorName);
}

//kannst Du auch folgendes verwenden:
foreach (errorCase err in errList)
{
   Console.WriteLine("Error Name: " + err.ErrorName);
}

//bzw:
foreach (var err in errList)
{
   Console.WriteLine("Error Name: " + err.ErrorName);
}

D
der-gee Themenstarter:in
4 Beiträge seit 2015
vor 9 Jahren

Ergebnis: Ich hatte zwei Fehler im Code. Einer war, dass ich dachte, ich könnte dem Objekt in der Liste neue Werte zuweisen. Dadurch kam es dazu, dass er in eine for Schleife gerannt ist und mir dort eine Liste bis zum Speicher-ende aufgepumpt hat.

Gelöst habe ich es dadurch, dass Änderungen an Zeit und Anzahl der Aufrufe nun in der Schleife setzte und dies über einen

bool notInserted = true 

merke. Wenn dieser true bleibt (hier bitte Euch einen Vertreter einer Subkultur, z.B. Punk oder Hip-Hopper denken, der das entsprechend Genre rhetorisch richtig ausdrückt), ist der Eintrag neu und wird erst nach der Schleife hinzugefügt.

So konnte ich auch wieder zu meinem erst Konstrukt zurückkehren und erst kurz vor Rückgabe dann das Objekt initialisieren und der Liste hinzufügen.

Mein Speicher und ich danken Euch herzlich für die schnelle Hilfe!

@CoLo: Danke für den foreach Tipp, wird auch meistens gemacht. In dem Fall waren die Schleifen aus dem "Problem-Code" kopiert, wo ich mir ggf. später die Indizes anschauen und verstehen wollte.

Schöne Grüße,
der-gee