«Boxing» (Решение)
Ответ
Foo
Foo
Foo
Bar
Baz
Foo
Объяснение
Ключевым моментом в понимании примера является тот факт, что при вызове Console.WriteLine
используется перегруженный вариант метода, принимающий аргумент типа object
. Поэтому передаваемая в него структура упаковывается. Это означает, что в управляемой куче создаётся копия структуры, метод ToString()
отрабатывает для упакованной копии. Теперь разберём пример по строчкам:
var foo = new Foo();
Console.WriteLine(foo); // Displays "Foo" (value == 0)
Console.WriteLine(foo); // Displays "Foo" (value == 0)
Мы создали экземпляр структуры Foo
и дважды выполнили для него Console.WriteLine(foo)
. Дважды выполнилась копирование и упаковка структуры, ToString()
вызвалось для копии, не тронув оригинал. Изначально Foo.value == 0
, так что в обоих случаях выведется "Foo"
.
object bar = foo;
object qux = foo;
object baz = bar;
Тут мы явно выполняем упаковку структуры. Объекты bar
и qux
указывают на разные копии структуры, т.к. мы выполнили две отдельных операции упаковки. Объект baz
указывает на ту же копию структуры, что и bar
, т.к. в третьей строчке мы просто выполнили копирование ссылки.
Console.WriteLine(baz); // Displays "Foo" (value == 0)
Console.WriteLine(bar); // Displays "Bar" (value == 1)
Console.WriteLine(baz); // Displays "Baz" (value == 2)
В этих трёх строчках мы работаем с одной и той же копией структуры, обращаясь к ней по ссылке (bar
и baz
представляют собой одну и ту же ссылку).
Console.WriteLine(qux); // Displays "Foo" (value == 0)
А в этой строчке мы работаем с копией структуры, для которой метод ToString()
ещё ни разу не вызывался. Поэтому выведется "Foo"
.