获取并设置初始化中的误解:Jeffrey Richter,CLR通过C#

本文关键字:Richter Jeffrey CLR 通过 误解 设置 初始化 获取 | 更新日期: 2023-09-27 18:20:03

我刚刚在Jeffrey Richter的书(CLR via C#4.0,第257页)中发现了一些奇怪的代码,并误解了为什么它能如此工作。

    public sealed class Classroom
    {
        private List<String> m_students = new List<String>();
        public List<String> Students { get { return m_students; } }
        public Classroom() { }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Classroom classroom = new Classroom {
                Students = { "Jeff", "Kristin" }
            };
            foreach (var student in classroom.Students)
                Console.WriteLine(student);
        }
    }

结果:

Jeff
Kristin

正如您所看到的,我们有一个名为"Students"的访问器属性,它只有getter(而不是setter

Classroom classroom = new Classroom {
    Students = { "Jeff", "Kristin" }
};

我一直认为,当变量在表达式的"左侧"(int I=1)时,编译器应该访问setter函数,而当变量在"右侧"(int x=I+2)时,应该访问getter函数。

为什么Jeffrey的代码中有如此有趣的行为(可能只是为了我?如果是这样的话,很抱歉)。

获取并设置初始化中的误解:Jeffrey Richter,CLR通过C#

来自C#5规范的第7.6.10.2节:

在等号之后指定集合初始化项的成员初始化项是嵌入集合的初始化项。初始值设定项中给定的元素被添加到字段或属性引用的集合中,而不是将新集合分配给字段或属性。字段或属性的集合类型必须满足§7.6.10.3中规定的要求。

所以这个代码:

Classroom classroom = new Classroom {
    Students = { "Jeff", "Kristin" }
};

相当于:

Classroom tmp = new Classroom();
tmp.Students.Add("Jeff");
tmp.Students.Add("Kristin");
Classroom classroom = tmp;

基本上,对象初始值设定项中的=与独立赋值语句并不完全相同。

编辑:此代码

Classroom classroom = new Classroom {
    Students = new List<string> { "Jeff", "Kristin" }
};

将无法编译,因为尝试调用Student的setter。