为什么集合初始化程序与仅使用getter的属性一起工作?

这对我来说是非常不可预测的代码结果。

我没想到这段代码会产生这样的结果。

所以,我读了Jeffrey Richter的书(clr ia c#),这个代码有一个例子。

internal class ClassRoom { private List _students = new List(); public List Students { get { return _students; } } } ClassRoom classRoom = new ClassRoom { Students = {"Mike", "Johny", "Vlad", "Stas"} }; foreach (var some in classRoom.Students) { Console.WriteLine(some); } 

并且,正如你们中的一些人可以建议我们可以在控制台中看到四个名字。 所以,我的问题是:

我们如何得到我们的名字,如果他们要进入学生和分别在_学生中,因为学生不存在而没有被分配。

__________EDIT_1_______________

我读了你的答案,谢谢你们。

但是,你知道,这是一种误解……我真的无法弄明白。

当我初始化学生时 ,我初始化_students

同样重要的是,当我从IEnumerable( 某些 )中获取变量时,我从学生那里获取变量? 我想不是。

我无法理解,究竟我在哪里分配变量(INITALIZE) _students集合?

谢谢你帮我解决一下!

这些其他答案几乎是正确的。 让我们通过它,实际上把它做好。

为什么集合初始化程序使用仅限getter的属性?

因为属性值没有改变。 属性引用的集合的内容是更改的内容。

将财产视为一个桶。 您无法更改属性引用的存储桶,但您可以更改存储桶的内容。

我们如何得到我们的名字,如果他们要进入学生和分别在_学生中,因为学生不存在而没有被分配。

学生财产从未被分配。 怎么会这样? 它没有二传手。

名称将添加到学生获取者引用的集合中。

当我初始化学生时,我初始化_students?

不._students的初始化是为_students赋值的行。

集合初始值设定项将值添加到现有集合中 。 变量_students已经初始化。

当我从IEnumerable(某些)获取变量时,我从学生那里获取变量?

你不接受任何变量 。 你拿价值 。 变量不是值; 变量包含值。 不要将存储与存储的值混淆。

我无法理解,究竟我在哪里分配变量(INITALIZE)_students集合?

_students变量在初始化_students的行中初始化。 集合的内容在包含内容的行中初始化。

也许它有助于列出发生的所有事情:

  • 创建一个新的Classroom对象; _students字段为null; 产生对象的引用。
  • 创建一个新的空列表; 对列表的引用将复制到新创建的Classroom对象的_students字段中。
  • 学生getter被称为对新Classroom对象的引用。 它返回_students的内容,它是对空列表的引用。
  • 该列表中添加了四个项目
  • 对Classroom对象的引用被复制到教室变量。

或者,在代码中,这相当于:

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

看,从来没有一个学生叫做。 没有必要。 它所做的就是获取_students中包含的引用,该引用已经由字段初始化程序初始化。

_students字段在构造时内部分配一次,缺少公共setter会阻止它从外部设置为不同的列表实例。 ClassRoom的对象初始化程序实际上并没有设置Students集合属性,而是简单地利用集合初始化程序语法初始项添加Students

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

以上类似于以下内容但不完全相同,因为对象初始化程序版本在填充集合之前不会执行对classRoom的赋值。

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

相反,请注意,由于缺少公共setter,以下会产生编译器错误,因此访问确实受到预期的限制……

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

通过说Students = {"Mike", "Johny", "Vlad", "Stas"}它正在做的是什么

属性Students返回基础List _students实例,并且您正在使用集合初始值设定项添加字符串文字。

那么,当我遍历学生时,我是否会遍历_students?

从技术上讲,您的_students是一个private变量,而且Students属性是该私有字段的包装,以便向外部消费者提供对该列表的访问。

因此,当您说Students = ...您实际上正在设置或初始化私有字段,因为访问Students会返回List实例。