These other answers are almost right. Let's go through it and actually get it all right.
Why does a collection initializer work with a getter-only property?
Because the property value is not changed. The contents of the collection that the property refers to is what is changed.
Think of a property as a bucket. You can't change which bucket the property refers to, but you can change the contents of the bucket.
How do we get our names, if they are going to get in Students and respectively in _students, that were not assigned because of nonexistence of Students setter.
The Students property is never assigned, at all. How could it be? It has no setter.
The names are added to the collection referred to by the Students getter.
When I Initialize Students, I initialize _students ?
No. The initialization of _students is the line which assigns a value to _students.
The collection initializer adds values to an existing collection. The variable _students has already been initialized.
when I take variable from IEnumerable(some), I am take variable from Students ?
You don't take a variable from anything. You take values. Variables are not values; variables contain values. Don't confuse the storage with the value stored.
I can't understand, WHERE exactly I assign variables(INITALIZE) _students collections ?
The _students variable is initialized in the line that initializes _students. The contents of the collection are initialized in the line that has the contents.
Perhaps it will help to list everything that happens in exactly the order it happens:
- a new Classroom object is created; the _students field is null; a reference to the object is produced.
- a new empty list is created; a reference to the list is copied into the _students field of the newly-created Classroom object.
- the Students getter is called on the reference to the new Classroom object. It returns the contents of _students, which is a reference to an empty list.
- four items are added to that list
- the reference to the Classroom object is copied to the classroom variable.
Or, in code, this is equivalent to:
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, there is never a setter of Students called. There doesn't need to be. All it does is gets the reference contained in _students, which already has been initialized by the field initializer.