Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get and set misunderstanding in initialisation: Jeffrey Richter, CLR via C#

Tags:

c#

.net

clr

I've just found strange for me code in Jeffrey Richter book (CLR via C# 4.0, page 257) and have misunderstanding why it works so.

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

Result:

Jeff
Kristin

As you can see, we have an accessor property named 'Students', which has only getter (not setter!), but in 'Main' function, when we'd like to initialize 'classroom' variable, we initializing 'Students' field of 'Classroom' type:

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

I always thought, that when a variable in 'left-side' of expression (int i = 1), then compiler should access to setter function, and when in 'right-side' (int x = i + 2) to getter function.

Why in Jeffrey's code so interesting behavior (may be it's just for me? sorry if it's so).

like image 439
Maxim Zhukov Avatar asked Jun 26 '13 13:06

Maxim Zhukov


1 Answers

From section 7.6.10.2 of the C# 5 spec:

A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property. The field or property must be of a collection type that satisfies the requirements specified in §7.6.10.3.

So this code:

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

is equivalent to:

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

Basically, = within an object initializer isn't exactly the same as a standalone assignment statement.

EDIT: This code

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

would fail to compile, as that would try to call a setter for Student.

like image 128
Jon Skeet Avatar answered Nov 16 '22 06:11

Jon Skeet