Laden...

Kopierte List<T> Änderung in der Kopie ändert auch Oroginal

Erstellt von Emskop vor 3 Jahren Letzter Beitrag vor 3 Jahren 883 Views
E
Emskop Themenstarter:in
3 Beiträge seit 2020
vor 3 Jahren
Kopierte List<T> Änderung in der Kopie ändert auch Oroginal

Ich möchte einen Index aus einer Liste kopieren und diesen dann nur in der Kopie verändern ohne das die Oroginal Liste verändert wird.

Das einzige was ich bisher gefunden haben ist der unten beschrieben weg zum kopieren der Klasse habe die unabhängigkeit der beiden Liste über den jetzt auskommentierten remove befehl getest.

Wenn ich aber LastData[0].TS mit einem anderen Wert beschreibe wird Lst_TL_Data[0].TS auch mit geändert.

Habe das ganze vorher übder den Add befehl versucht welcher aber scheinbar nur die Referenz kopiert ?

Zudem wäre es schön, nur den benötigten Datensatz über den index in die neue liste zu kopieren.


public class QHMI_DATALOG_CS
    {
        public int ID { get; set; }

        public DateTime TS { get; set; }

        public string DATASOURCE { get; set; }

        public string DATATYPE { get; set; }
        public string VARNAME { get; set; }
        public string VALUE { get; set; }

        public string Quality { get; set; }

        public string MESSAGE { get; set; }

}


 

      public void CreateLastTimestamp()
        {
            int n1 = 0;
            LastData.Clear();

            //Kopiere letzten Datensatz aus Lst_TL_Data und füge diesen in LastData ein
            if (Lst_TL_Data.Count > 0)
            {
                // Kompletten Inhalt der liste Kopieren  (nicht nur die Referenz) und in  LastData einfügen
                this.LastData = new List<QHMI_DATALOG_CS>(this.Lst_TL_Data);
                
                // Lösche Datensätze bis auf den letzten
                while(LastData.Count > 1 )
                {
                    LastData.RemoveAt(0);        
                }
            }
        

            if (Lst_TL_Data.Count <= 0)
            {
                // Kompletten Inhalt der liste Kopieren  (nicht nur die Referenz) und in  LastData einfügen
                this.LastData = new List<QHMI_DATALOG_CS>(this.DataFirstPoint);

                // Lösche Datensätze bis auf den letzten
                while (LastData.Count > 1)
                {
                    LastData.RemoveAt(0);
                }
            }

          //  LastData.RemoveAt(0);


            // Soll nur den Zeitstempel der Liste LastData index 0 verändern
            
             LastData[0].TS = dt_Uebergabe_SQL_Ende;
        }

A
764 Beiträge seit 2007
vor 3 Jahren

Hallo Emskop

Du hast zwar eine zweite Liste, aber die Objekte die du da rein machst, sind die selben! wie die aus der ersten List. Stichwort Reference Type.
Google spuckt unter anderem das hier aus: https://www.tutorialsteacher.com/csharp/csharp-value-type-and-reference-type

Ansonsten kannst du das letzte Objekt einer Liste zu einer anderen hinzufügen indem du nur das letzte der neuen Liste hinzufügts:


LastData.Add(Lst_TL_Data.Last());

Übrigens ist Lst_TL_Data ein ungeschickt gewählter Name:
Heißt das Last_TL_Data oder List_TL_Data?

Ein kleiner Buchstabe, der die Lesbarkeit deutlich erhöht.

Gruß
Alf

E
Emskop Themenstarter:in
3 Beiträge seit 2020
vor 3 Jahren

Moin Alf Ator,

danke für die schnelle antwort.

Jetzt stellt sich mir die Frage ob ich die Daten auf den der Reference Type zeigt irgend wie duplizieren kann und mit einer anderen Liste verbinden kann.

Oder ob der einzige weg ist, die Daten erneut aus der SQL-Datenbank zu Laden und mit der zweiten Liste zu verknüpfen ? Damit ich beide unabhängig voneinander bearbeiten kann.

DieListen habe ich gerade umbenannt:
List_TL_Data (Oroginal Liste)
List_LastData (Liste in der ein Teil der oroginal Liste gespeichert und bearbeitet werden soll ohen die oroginal Liste zu verändern)

Gruß
Emskop

H
48 Beiträge seit 2020
vor 3 Jahren

was willst du machen sowas wie ein undo oder was ist der sinn?? so wie du reference types behandelst ist es ein grundlegend falsches vorgehen das du anders lösen solltest.
es macht jedenfalls keinen sinn eine liste parallel zu bearbeiten und an den sql server zu schicken
dazu sei noch gesagt das man kein DateTime in der datenbank verwenden weil das die zeitzone verliert sondern man verwendet DateTimeOffset mit datetime2 als spaltentyp

12 Beiträge seit 2020
vor 3 Jahren

Hi,

ich hab mal eine Liste kopiert damit diese unabhängig voneinander bearbeitet werden können (2 seperate Listen, wobei die eine ein Klone ist)


ListWhichIWantToCopy.ForEach((item) => { ListWhichIsNew.Add(new QHMI_DATALOG_CS(item)); });

Aber dafür muss die Klasse (hier QHMI_DATALOG_CS) dann einen Konstruktor haben z. B.


public QHMI_DATALOG_CS(QHMI_DATALOG_CS cloneItem)
        {
            _interneVar1 = cloneItem.InterneVar1;
        }

Vielleicht hilft dir das weiter.

E
Emskop Themenstarter:in
3 Beiträge seit 2020
vor 3 Jahren

vorab ich bin noch blutiger Anfänger im Prozess Learning by doing.

mein vorhaben:

ich bekomme Anlagendaten aus einer Datenbank, Geschwindigkeiten usw. diese versuche ich momentan per C# auszuwerten Produktionszeiten, Nutzeffekt, prozentuale Stillstände und deren Gründe ...

Die Daten werden nur bei Zustandsänderungen in die DB geschriebn.

Daher lade ich mir die Daten für einen gewissen Zeitraum und muss den ersten und den letzten Datenpunkt ergänzen. Um sauber rechnen zu können.

Der letzte Datenpunkt innerhalb des Zeitraumes der SQL Datenbak entspricht dem Zustand des Endzeitpunktes meiner Auswertung daher wollte ich diesen in eine seperate Liste kopieren und den Zeitstempel ändern um danach beide Listen zusammen zu führen.

Und dann mit der Zusammengeführetn Liste zu Arbeiten.

Ich bin das Problem jetzt umganagen indem ich mir nur den benötigenten Datensatz aus der DB in eine neu erstellte Liste Lade.

cloneItem scheint der richtige weg zu sein allerdings möchte ich an der Klasse QHMI_DATALOG_CS momentan ungern was ändern, da diese an vielen stellen verwendet wird.

Danke für die schnellen Antworten.

12 Beiträge seit 2020
vor 3 Jahren

Zur Ergänzung noch die Info bzgl.:

[...]allerdings möchte ich an der Klasse QHMI_DATALOG_CS momentan ungern was ändern, da diese an vielen stellen verwendet wird.

Wenn du in deiner Klasse den alten Konstruktor nicht löscht oder veränderst, dürfte es bei den anderen Stellen im Code, wo du diesen Konstruktor schon benutzt, nichts ändern. Bzw. du hast ihn noch nicht implementiert daher würde ich den dann noch hinzuschreiben.

Spontan würde ich die Klasse wie folgt ändern um so auch an anderen Stellen noch das alte Verhalten zu gewährleisten:


    public class QHMI_DATALOG_CS
    {
        public int ID { get; set; }

        public DateTime TS { get; set; }

        public string DATASOURCE { get; set; }

        public string DATATYPE { get; set; }
        public string VARNAME { get; set; }
        public string VALUE { get; set; }

        public string Quality { get; set; }

        public string MESSAGE { get; set; }

        /// <summary>
        /// Default Konstruktor der für die  anderen Programmstellen dann benutzt wird
        /// </summary>
        public QHMI_DATALOG_CS()
        {

        }
        /// <summary>
        /// Konstruktor um die Liste mit QHMI_DATALOG_CS zu klonen, Item für Item mit ForEach
        /// </summary>
        /// <param name="cloneItem">Item das ich kopieren möchte (ohne Referenz)</param>
        public QHMI_DATALOG_CS(QHMI_DATALOG_CS cloneItem) :this()
        {
            ID = cloneItem.ID;
            TS = DateTime.Parse(cloneItem.TS.ToString()); // DateTime ist glaube ich ein Referenztyp, daher würde ich in String wandeln und neues Objekt daraus machen, müsste man wenn man das nicht will einfach testen
            DATASOURCE = cloneItem.DATASOURCE;
            DATATYPE = cloneItem.DATATYPE;
            VARNAME = cloneItem.VARNAME;
            VALUE = cloneItem.VALUE;
            Quality = cloneItem.Quality;
            MESSAGE = cloneItem.MESSAGE;
        }

    }

4.931 Beiträge seit 2008
vor 3 Jahren

@SimpleTool: DateTime ist eine Struktur, also ein Wertetyp.
Daher reicht:


TS = cloneItem.TS;

5.657 Beiträge seit 2006
vor 3 Jahren

Ansonsten gibt es auch die MemberwiseClone-Methode

Weeks of programming can save you hours of planning