Erzeugen einer neuen Instanz einer Liste in C#
Ich habe ein problem bei der Verwendung von C#, wenn ich initialisieren einer bestimmten Liste, sagen wir List<T> exampleList
mit einem anderen bereits vorhandenen Liste, können sagen, toModify wie diese: List<T> exampleList = new List<T>(toModify)
. Wenn ich später ändern toModify Liste der neu erstellten Liste auch ändert sich. Wenn es geht, den Wert durch Referenz sollte nicht den Wert von exampleList bleiben die gleichen, da war es generiert aus den anderen?
TLDR: Wert einer Liste, die ich initialisieren mit einer anderen Liste(zweite Liste) ändert, wenn ich die zweite Liste. Ich komme aus einem Java-hintergrund und kann nicht verstehen, warum dies geschieht. Ich habe immer zu verwenden-Klon?
- C#'s Verhalten ist genau das gleiche wie Java' s Verhalten in dieser Hinsicht. Können Sie erklären, was Sie meinen, wenn Sie sagen, dass Sie "ändern" in der Liste? Vielleicht bieten einen minimalen code-Beispiel, um zu zeigen das Verhalten, das Sie beobachten?
- C# - Konzepte: Wert-vs. Referenztypen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Lassen Sie uns ein Beispiel verwenden :
Ausgabe : 999
Der Hauptgrund für dieses ist, dass, obwohl wir erstellen neue
List<T>
Objekt (ja, collection-Objekt), verweist auf einen neuen Speicher im verwalteten heap, aber es funktioniert immer noch mit Referenzen auf dieselben Objekte.Erstellung einer Liste der neuen (!) Objekte mit gleichen Werten müssen Sie Elemente kopieren, irgendwie, eine Möglichkeit ist die Verwendung von LINQ
.Select()
Methode, um neue Objekte zu erstellen undToList()
Methode, um es konvertieren zu-Liste :Ausgang : 5
Ja.
Erstellen Sie eine neue Liste mit denselben Elementen wie die alte Liste. Wenn Sie die Auswahl in der ersten Liste, die Elemente, die in der zweiten bleiben.
Aber wenn Sie eine Eigenschaft ändern für eines der Elemente in der ersten Liste, dann ist es das gleiche Objekt in der zweiten Liste.
So, beide Liste sind Verweise auf die gleichen Objekte im Speicher. Wenn Sie schreiben
list1[0].SomeProperty = 1
Sie ändern, dass die Verwendung von Objekt verweisen, ist das gleiche inlist2
, so dass änderungen in der zweiten Liste.Für so Klonen Sie eine Liste und generieren neue Referenzen für Elemente, überprüfen Sie diese SO Antwort.
In der folgenden Zeile:
erstellen Sie eine Liste von T-Aufruf
List<T>
's Konstruktor, der ein argument vom TypIEnumerable<T>
. Für weitere Informationen über die letztere, bitte haben Sie einen Blick hier.Methode, die die Argumente in C# übergeben werden standardmäßig by-value und nicht by-reference. Sie können per Referenz übergeben werden, aber Sie müssen explizit angeben, diese in der Signatur der entsprechenden Methode mit der
ref
Schlüsselwort und an der Stelle, rufen Sie diese Methode, verwenden wieder das gleiche keyword. Also dietoModify
wird als Wert übergeben an den Konstruktor vonList<T>
.Was ist die Bedeutung dieses?
In C# - Typen können in zwei Kategorien unterteilt werden (trotz der Tatsache, dass alle Typen Erben aus dem System.Objekt):
Wenn wir an den Wert-Typ, der als argument übergeben wir eine Kopie ist es Wert. Jede änderung, die wir machen, in der entweder der ursprüngliche Wert oder in der Kopie der original-Wert nicht reflektiert wird, zu einer anderen. Auf der anderen Seite, wenn wir an einem Referenz-Typ als argument übergeben wir eine Kopie der Referenz. So, jetzt haben wir zwei Verweise (Zeiger), der auf der gleichen Position im Speicher. That being said, es ist klar, dass, wenn wir ändern jede Eigenschaft des Objekts, in dem beide Referenzen Punkte zu, wäre dies sichtbar von beiden.
In Ihrem Fall ist dies, was geschieht.
toModify
ist eine Liste von Referenz-Typen (unter der Haube haben Sie ein array, dessen Elemente Referenzen auf andere Objekte). So dass jede änderung, die auf die Elemente der ersten ListetoModify
, spiegelt sich in der Liste, die Sie konstruieren auf der Grundlage dieser Liste.Ein einfaches Beispiel, das Sie verwenden können, um zu überprüfen, die oben genannten ist folgende: