«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".

Задача