Предположим, у вас есть назначение члену доступа в форме:
expr.field = value;
Значением экземпляра структуры по определению является его значением . Если вы пытаетесь изменить поле структуры, то вы должны пытаться изменить хранилище , в котором хранится значение . То есть вы должны пытаться изменить переменную . Поле является переменной, которая является частью другой переменной.
Следовательно, если expr является типом структуры, тогда expr должен быть переменной .
В вашем примере expr не является переменной. Это свойство, и результатом доступа к свойству является значение , а не переменная .
Это может быть не ясно. Давайте попробуем аналогию.
Представьте, что у вас есть лист бумаги, представляющий значение структуры. На бумаге есть коробка с надписью «c», которая содержит число.
Когда вы говорите "b.c = 2.0;" то, что он делает, идет и находит хранилище, связанное с b, и делает фотокопию куска бумаги, который он там находит. Затем вы стираете номер на копии, которую вам передали, и заменяете ее на 2.0. Это делает то, что вы хотите? Конечно, нет. Это не меняет ценность куска бумаги, хранящегося в b! Типы значений копируются по значению . Поскольку это не делает то, что вы хотите, это незаконно в C #.
Теперь предположим, что у вас есть лист бумаги, представляющий ценность класса. На бумаге есть коробка с надписью «у», которая содержит число.
Когда вы говорите "x.y = 2.0;" то, что он делает, идет и находит хранилище, связанное с x, и вручает вам один конец ленты. Другой конец ленты прикреплен к листу бумаги, который является хранилищем, связанным с x. Вы следуете за лентой, найдите поле с надписью y на другом конце и замените число на 2,0.
Типы ссылок копируются по ссылке ; вы не получаете копию значения в хранилище, вы получаете что-то, что позволяет найти хранилище .
В этом разница между типами значений и ссылочными типами; типы значений копируются по значению, ссылочные типы копируются по ссылке.
Теперь понятно?