为什么集合初始化程序与getter-only属性一起使用?

时间:2016-06-26 19:21:36

标签: c# properties clr getter-setter

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

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

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

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);
}

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

我们如何获得我们的名字,如果他们要进入学生和_students,那些因为学生不存在而没有被分配。

__________ EDIT_1 _______________

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

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

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

当我从IEnumerable( some )中获取变量时,重要的是, 我从学生变量? 我想不是。

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

感谢您帮助我弄明白!

3 个答案:

答案 0 :(得分:1)

_students字段在构建时内部分配一次,缺少公共setter会阻止它从外部设置为不同的列表实例。 ClassRoom的对象初始值设定项实际上并未设置Students集合属性,而是简单地利用集合初始值设定项语法将添加初始项目添加到Students ... < / p>

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<string> { "Mike", "Johny", "Vlad", "Stas" }
}

答案 1 :(得分:1)

这些其他答案几乎正确。让我们来看看它实际上是否正常。

  

为什么集合初始值设定项使用仅限getter的属性?

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

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

  

我们如何获得我们的名字,如果他们要进入学生和_students,那些因为学生不存在而没有被分配。

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

这些名字被添加到学生获取者所引用的集合中。

  

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

没有。 _students的初始化是为_students赋值的行。

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

  

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

你不能从任何东西中获取变量。你拿。变量不是值;变量包含值。不要将存储与存储的值混淆。

  

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

_students变量在初始化_students的行中初始化。集合的内容在具有内容的行中初始化。

也许这将有助于按照发生的顺序列出发生的所有事情:

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

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

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

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

答案 2 :(得分:0)

Students = {"Mike", "Johny", "Vlad", "Stas"}正在做什么

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

  

所以,当我遍历学生时,我会迭代学生   _students?

从技术上讲,您的_studentsprivate变量,Students属性是该私有字段的包装,可以将该列表授予外部消费者。

因此,当您说Students = ...实际上是设置或初始化私有字段时,因为访问Students会让您返回List<string>个实例。