В этом конкретном случае хороший компилятор должен быть в состоянии устранить общее выражение и сгенерировать в значительной степени оптимальный код. Так как вы обращаетесь к примитивным типам, a-> b-> c может быть оценен один раз и использован во всем методе.
Вызов C :: USize () или доступ не примитивного типа в «классе C» нарушит этот шаблон и заставит компилятор переоценить a-> b-> c для следующей строки.
a->b->c.x = 10;
a->b->c.Usize(); // <-- Usize() may change a.b so the next line references another B.
a->b->c.y = 5;
Это потому, что компилятор не может на 100% быть уверенным, что вызов метода / оператор не изменяет a, a.b или b.c, поэтому он должен переоценить цепочку, чтобы убедиться.
Я бы почти сказал, что беспокоиться об этом на данном этапе преждевременной оптимизации. Тем не менее, ваш второй пример более читабелен и помогает компилятору не догадываться, если вы вставите какие-либо вызовы методов позже, поэтому я бы пошел на это.