2016-06-26 33 views
2

Es ist sehr unvorhersehbares Ergebnis des Codes für mich.Warum funktioniert der Auflistungsinitialisierer nur mit der Getter-only-Eigenschaft?

Ich habe nicht erwartet, dass dieser Code ein solches Ergebnis erzeugt.

Also lese ich Jeffrey Richters Buch (clr ia C#) und es gibt ein Beispiel mit diesem Code.

internal class ClassRoom 
{ 
    private List<String> _students = new List<string>(); 
    public List<String> Students { get { return _students; } } 
} 

ClassRoom classRoom = new ClassRoom 
{ 
    Students = {"Mike", "Johny", "Vlad", "Stas"} 
}; 

foreach (var some in classRoom.Students) 
{ 
    Console.WriteLine(some); 
} 

Und wie einige von Ihnen vorschlagen können wir in der Konsole vier Namen sehen. Also, meine Frage ist:

Wie bekommen wir unsere Namen, wenn sie in Studenten bzw. in _students bekommen, die nicht wegen Nichtexistenz von Studenten Setter zugewiesen wurden.

__________EDIT_1_______________

Ich lese Ihre Antworten, und ich danke Ihnen für diese.

Aber weißt du, es ist ein bisschen Missverständnis ... Ich kann es wirklich nicht herausfinden.

Als ich initialisieren Students, ich initialisieren _students?

Und was nicht weniger wichtig ist, als ich von der IEnumerable Variable nehmen (einige), Ich bin nehmen Variable von Studenten? Ich denke nicht.

Ich kann nicht verstehen, wo genau ich Variablen zuweisen (INITALISIEREN) _students Sammlungen?

Vielen Dank für Hilfe, um es herauszufinden!

+0

Durch Hinzufügen von Dingen zu der Liste. – SLaks

+0

Yeap. Und wenn wir "einige" Variable nehmen, nehmen wir Variable von _students, nicht wahr? –

Antwort

1

Diese anderen Antworten sind fast rechts. Lass uns das durchgehen und es wirklich gut machen.

Warum funktioniert ein Auflistungsinitialisierer mit einer Getter-only-Eigenschaft?

Da der Eigenschaftswert nicht geändert wird. Der Inhalt der Sammlung, auf die sich die Eigenschaft bezieht, wird geändert.

Denken Sie an eine Eigenschaft als Eimer. Sie können nicht ändern, auf welchen Bucket die Eigenschaft verweist, Sie können jedoch den Inhalt des Buckets ändern.

Wie bekommen wir unsere Namen, wenn sie in Studenten bzw. in _students aufgenommen werden, die wegen Nichtexistenz von Studenten Setter nicht zugewiesen wurden.

Die Students-Eigenschaft wird nie zugewiesen. Wie könnte es sein? Es hat keinen Setter.

Die Namen werden zu der Sammlung hinzugefügt, auf die sich der Student Getter bezieht.

Wenn ich Studenten initialisiere, initialisiere ich _students?

Nein. Die Initialisierung von _students ist die Zeile, die _students einen Wert zuweist.

Der Sammlungsinitialisierer fügt Werte zu einer vorhandenen Sammlung hinzu. Die Variable _students wurde bereits initialisiert.

Wenn ich Variablen von IEnumerable (einige) nehme, nehme ich Variable von Studenten?

Sie nehmen keine Variable von allem. Sie nehmen Werte. Variablen sind keine Werte; Variablen enthalten Werte. Verwechseln Sie den Speicher nicht mit dem gespeicherten Wert.

Ich kann nicht verstehen, WO genau ich Variablen zuweisen (INITALIZE) _students Sammlungen?

Die Variable _students wird in der Zeile initialisiert, die _students initialisiert. Die Inhalte der Sammlung werden in der Zeile initialisiert, die den Inhalt enthält.

Vielleicht wird es helfen, alles aufzulisten, die in genau der Reihenfolge geschieht es passiert:

  • ein neues Klassenobjekt erstellt wird; das Feld _students ist null; ein Verweis auf das Objekt wird erzeugt.
  • eine neue leere Liste wird erstellt; Ein Verweis auf die Liste wird in das _students-Feld des neu erstellten Classroom-Objekts kopiert.
  • der Student Getter wird auf den Verweis auf das neue Classroom-Objekt aufgerufen. Es gibt den Inhalt von _students zurück, was eine Referenz auf eine leere Liste ist.
  • vier Elemente werden zu dieser Liste hinzugefügt
  • Der Verweis auf das Classroom-Objekt wird in die Klassenraumvariable kopiert.

Oder in Code, das ist äquivalent zu:

c = create a Classroom 
c._students = null 
l1 = create a List<string> 
c._students = l1 
l2 = c.Students -- which returns c._students 
l2.Add("...") -- four times 
classRoom = c 

See, es nie ein Setter von Studenten aufgerufen. Es muss nicht sein. Es wird nur die Referenz in _students abgerufen, die bereits vom Feldinitialisierer initialisiert wurde.

+0

Vielen Dank, dass Sie diese Informationen zugänglich gemacht haben! –

0

von Students = {"Mike", "Johny", "Vlad", "Stas"} sagen, was es ist

Eigenschaft tun Students die zugrunde liegende List<String> _students Instanz zurückgibt und dass Sie die Stringliteral eine Auflistungsinitialisierer mit hinzufügen.

Also, wenn ich durch Studenten iteriere, bin ich durch die _students?

Technisch ja, Ihr _students ist eine private Variable und Students Eigenschaft ist Wrapper um diesen privaten Bereich Zugang zu dieser Liste außerhalb der Verbraucher zu geben.

Also, wenn Sie sagen Students = ... Sie setzen oder Initialisierung der privaten Feld tatsächlich seit dem Zugriff Students gibt Ihnen die List<string> Instanz zurück.

+0

Ja, es ist eine Art verständliche Dinge ... –

+0

Also, wenn ich durch Studenten Iteriere, bin ich durch die _students iterieren? –

+0

@VladislavHromyh, siehe in der Antwort bearbeiten, wenn das hilft. – Rahul

1

Das Feld _students wird intern zum Zeitpunkt der Erstellung einmal zugewiesen, das Fehlen eines öffentlichen Setter verhindert, dass es von außen auf eine andere Listeninstanz gesetzt wird.Classroom Objektinitialisierer nicht tatsächlich die Einstellung der Students Sammlung Eigenschaft sondern es wird einfach Auflistungsinitialisierer Syntax hinzufügen die ersten Artikel zu Students ...

ClassRoom classRoom = new ClassRoom 
{ 
    Students = { "Mike", "Johny", "Vlad", "Stas" } 
}; 

Die obige Nutzung ist ähnlich der folgenden, wenn auch nicht genau Gleiches, da die Objektinitialisiererversion erst nach dem Auffüllen der Sammlung die Zuweisung an classRoom durchführt.

ClassRoom classRoom = new ClassRoom(); 
classRoom.Students.Add("Mike"); 
classRoom.Students.Add("Johny"); 
classRoom.Students.Add("Vlad"); 
classRoom.Students.Add("Stas"); 

Im Gegensatz zu beachten, dass die folgenden einen Compiler-Fehler aufgrund des Fehlens des öffentlichen Setter produzieren wird daher der Zugang wirklich wie erwartet eingeschränkt ...

ClassRoom classRoom = new ClassRoom 
{ 
    Students = new List<string> { "Mike", "Johny", "Vlad", "Stas" } 
} 
+0

Diese Antwort ist * fast * richtig. Die Zuweisung zu 'classRoom' geschieht * nachdem * die Liste gefüllt ist, nicht vorher. Wenn eines der Adds eine Ausnahme ausgibt, wäre zum Beispiel "classRoom" noch nicht zugewiesen. –

+0

@EricLippert, Also wahr ... Ich habe meine Antwort bearbeitet, um diesen Punkt zu reflektieren. Vielen Dank. – blins

+0

Vielen Dank für Ihre Antwort! –