为什么集合初始化程序与仅使用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
是一个private
变量,而且Students
属性是该私有字段的包装,以便向外部消费者提供对该列表的访问。
因此,当您说Students = ...
您实际上正在设置或初始化私有字段,因为访问Students
会返回List
实例。