Примитивные типы C # (double, int и т. Д.) И различия структур - PullRequest
1 голос
/ 19 января 2011

меня смущают структуры.

class A
{
  double a { get; set; }  
  MyStruct b { get; set; }

  void Modify()
  {
     a = 1.0;    // This compiles.
     b.c = 2.0;  // Assuming c is a double. This gives the known error.
  }
}

Теперь, почему я могу установить значение структуры a, а не поля структуры b?Ответ, который я прочитал, состоит в том, что у меня есть копия b, а не поле поддержки b.По той же логике у меня должна быть копия а, а не а, как это объясняет, что свойство изменяется после разрешенного присвоения

a = 1.0;

?Спасибо.

РЕДАКТИРОВАТЬ:
Также для того, чтобы по-прежнему использовать b внутри класса A, «фильтруется» методами set и get, а не напрямую с помощью вспомогательного поля _bчто-то, что могло бы выглядеть следующим образом:

MyStruct _b;
MyStruct b { get { return _b; } set { _b=value; } }

, а затем использовать поле

_b

, как правильно указано в ответах, я подумал о глупом способе «обернуть»свойство в одномерном массиве размером 1.

MyStruct[] b { get; set; }

своего рода обертывание структуры с классом.Я не знаю вычислительных затрат, но я предпочел использовать поле непосредственно внутри класса A.

ОТВЕТ: Хорошо, путаница в этом вопросе возникает, когда вы привыкли интерпретировать свойства как поля в вашем уме.Если вы правильно интерпретируете свойства - , как это делает MsIL - все вещи успокаиваются.Все ответы и комментарии, приведенные ниже, актуальны.(Извините за плохой английский.)

Ответы [ 4 ]

5 голосов
/ 19 января 2011

Вы делаете две разные вещи.Вот пример выполнения одинаковых вещей в обоих местах:

a = 1.0;
b = new MyStruct(2.0);

В обоих этих случаях оператор присваивания вызывает «установщик» свойства.Вы можете думать об этом как:

this.SetA(1.0);
this.SetB(new MyStruct(2.0));

В качестве более сложного примера, если вы написали:

a = a + 1.0;

, что эквивалентно:

this.SetA(1.0 + this.GetA());
4 голосов
/ 19 января 2011

Предположим, у вас есть назначение члену доступа в форме:

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.

Типы ссылок копируются по ссылке ; вы не получаете копию значения в хранилище, вы получаете что-то, что позволяет найти хранилище .

В этом разница между типами значений и ссылочными типами; типы значений копируются по значению, ссылочные типы копируются по ссылке.

Теперь понятно?

1 голос
/ 19 января 2011

Ваша логика немного не в порядке.

В первом примере вы заменяете double на новый double.

Во втором примере вы не заменяетеструктура с другой структурой.Вместо этого вы пытаетесь изменить какое-то поле структуры.

Чтобы сделать похожие вещи, вам нужно будет сделать:

a = 10.1;
b = new MyStruct(10.1);

a = 11.1;
b = new MyStruct(11.1);
1 голос
/ 19 января 2011

Эта ошибка возникает при попытке изменить значение.

Когда вы пишете a = 1.0, вы заменяете значение - вы присваиваете весь тип значения новому значению. a = 1.0 эквивалентно b = new MyStruct().

Это еще одна причина, по которой изменчивые структуры являются злом .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...