Wie man IEnumerable<T> readonly?
Warum sind die Listen list1Instance
und p
im Main
- Methode der folgende code zeigt auf der gleichen Kollektion?
class Person
{
public string FirstName = string.Empty;
public string LastName = string.Empty;
public Person(string firstName, string lastName) {
this.FirstName = firstName;
this.LastName = lastName;
}
}
class List1
{
public List<Person> l1 = new List<Person>();
public List1()
{
l1.Add(new Person("f1","l1"));
l1.Add(new Person("f2", "l2"));
l1.Add(new Person("f3", "l3"));
l1.Add(new Person("f4", "l4"));
l1.Add(new Person("f5", "l5"));
}
public IEnumerable<Person> Get()
{
foreach (Person p in l1)
{
yield return p;
}
//return l1.AsReadOnly();
}
}
class Program
{
static void Main(string[] args)
{
List1 list1Instance = new List1();
List<Person> p = new List<Person>(list1Instance.Get());
UpdatePersons(p);
bool sameFirstName = (list1Instance.l1[0].FirstName == p[0].FirstName);
}
private static void UpdatePersons(List<Person> list)
{
list[0].FirstName = "uf1";
}
}
Können wir dieses Verhalten ändern out ändern Sie den Rückgabetyp der List1.Get()
?
Dank
Du musst angemeldet sein, um einen Kommentar abzugeben.
In der Tat
IEnumerable<T>
ist bereits readonly. Es bedeutet, dass Sie nicht zu ersetzen, alle Elemente in der zugrunde liegenden Auflistung mit verschiedenen Gegenständen. Das heißt, Sie können nicht ändern die Referenzen derPerson
Objekte, die in die Sammlung. Der TypPerson
ist nicht nur zu Lesen, allerdings, und da ist es ein Typ der Referenz (d.h. einclass
), Sie verändern seine Mitglieder über den Verweis.Gibt es zwei Lösungen:
struct
als Rückgabe-Typ (macht eine Kopie von dem Wert jedes mal, wenn Sie zurückgegeben, so wird der ursprüngliche Wert wird nicht geändert werden — und das kann teuer werden, übrigens)Person
geben, diese Aufgabe zu erfüllen.IEnumerable<T>
zurückT[]
,List<T>
oder was auch immer geben Sie es tatsächlich ist, und ändern Sie es, Gegenstände (selbst, nicht Ihre Eigenschaften).IEnumerable
seiner eigentlichen Art) bedeutet nicht, dass Sie immer sollte.IEnumerable<T>
ist nicht im wesentlichen eine readonly-Sammlung.Rückkehr eine neue Instanz von Person, die eine Kopie der
p
stattp
sich in Get(). Sie benötigen eine Methode, um eine Tiefe Kopie von ein Person-Objekt zu tun. Dies wird nicht machen Sie Sie nur Lesen, aber Sie wird anders sein als die in der ursprünglichen Liste.Sind Sie nicht auf das gleiche .Net Sammlung, sondern vielmehr, um die gleiche
Person
Objekte. Die Zeile:kopiert alle Person-Elemente von
list1Instance.Get()
Listep
. Das Wort "Kopien" hier bedeutet, dass Kopien der Referenzen. Also, Ihre Liste undIEnumerable
nur zufällig auf das gleichePerson
Objekte.IEnumerable<T>
ist immer readonly, per definition. Die Objekte, die im inneren sein kann veränderbar, wie in diesem Fall.Könnte man ein deepclone jedes Element in der Liste, und nie wieder Verweise auf Ihre ursprünglichen Elemente.
IEnumerable<T>
ist readonlyp
ist eine neue Kollektion, die nicht davon abhängiglist1instance
.Der Fehler, den du gemacht, ist, dass Sie dachte, dass diese Zeile
list[0].FirstName = "uf1";
würde sich nur ändern, eine der beiden Listen, wenn auf die Tatsache, das Sie gerade Bearbeiten
Person
Objekt.Die beiden Kollektionen unterscheiden, in der Sie nur zufällig den gleichen Positionen.
Um zu beweisen, dass Sie anders sind, versuchen Sie, hinzufügen und entfernen von Elementen aus einer der Listen, und Sie werden sehen, dass der andere gar nicht betroffen.
Zuerst, Ihre Liste in Ihrer Klasse öffentlich ist, so gibt es nichts zu stoppen jemand aus Sie direkt Zugriff auf die Liste selbst.
Zweitens, ich würde IEnumerable implementieren und bringe diese in meine GetEnumerator-Methode
Wenn Ihr person-Objekt ein reales Objekt, dann sollten Sie erwägen, eine unveränderliche version.
In dieser Art und Weise nicht möglich zu ändern, den Inhalt der Instanz, die einmal erstellt und daher ist es nicht wichtig, dass die bestehenden Instanzen wiederverwendet werden in mehreren Listen.
Dieser code bewirkt, dass eine abgeleitete Klasse, so wie verlangt, der den Rückgabetyp hat sich nicht verändert.
Tut es werfen eine Fehlermeldung, wenn Sie versuchen, ein Feld ändern (über die Eigenschaft), so ist 'nur Lesen'. Wenn Sie nicht wollen, um in der Lage sein, um die Werte zu ändern, ohne die original-the clone Antwort oben ist besser.