在初始化中得到并设置误解:Jeffrey Richter,CLR通过C#

FSo*_*ou1 9 .net c# clr

我刚刚在Jeffrey Richter的书中找到了奇怪的代码(CLR来自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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

结果:

Jeff
Kristin
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我们有一个名为'Students'的访问者属性,它只有getter(不是setter!),但在'Main'函数中,当我们想初始化'classroom'变量时,我们初始化'Students'字段"课堂"类型:

Classroom classroom = new Classroom {
    Students = { "Jeff", "Kristin" }
};
Run Code Online (Sandbox Code Playgroud)

我一直认为,当表达式(int i = 1)的'左侧'变量时,编译器应该访问setter函数,而当'right-side'(int x = i + 2)中的getter函数.

为什么在杰弗里的代码中有这么有趣的行为(可能只是为了我?对不起,如果是这样的话).

Jon*_*eet 23

从C#5规范的第7.6.10.2节:

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

所以这段代码:

Classroom classroom = new Classroom {
    Students = { "Jeff", "Kristin" }
};
Run Code Online (Sandbox Code Playgroud)

相当于:

Classroom tmp = new Classroom();
tmp.Students.Add("Jeff");
tmp.Students.Add("Kristin");
Classroom classroom = tmp;
Run Code Online (Sandbox Code Playgroud)

基本上,=在对象内初始值设定项与独立赋值语句不完全相同.

编辑:这段代码

Classroom classroom = new Classroom {
    Students = new List<string> { "Jeff", "Kristin" }
};
Run Code Online (Sandbox Code Playgroud)

将无法编译,因为它尝试调用setter Student.