2008-11-20 1 views
1

Допустим, у вас есть свойство, как:Что происходит, когда вы делаете задания на поля или свойства свойств

Person person1; 


public Person Captin{ 
    get{ 
     return person1; 
    } 
    set{ 
     person1 = value; 
    } 
} 

public void SomeFunction(){ 
    Captin.name = "Hook" 
} 

В этом случае, если вы установите имя свойства, мы знаем, что новое название Крюк get применяется к базовому значению person1. Что делать, если наша реализация была немного другая сказать:

public Person Captin{ 
    get{ 
     return ReadCaptinFromDisk(); 
    } 
    set{ 
     WriteCaptinToDisk(value); 
    } 
} 

public void SomeFunction(){ 
    Captin.name = "Hook" 
} 

В этом случае для базовое значение, чтобы установить должным образом, мы должны иметь набор кода в Captin Называется как часть задания на Captin.name.

Мне интересно знать, будет ли код набора параметров вызывать набор при назначении вызовов полей или методов в ссылках на свойства. особенно для такого рода ситуаций, когда значение должно распространяться на диск (и т. д.).

+0

_Мы знаем, что новое имя Hook будет применено к базовому значению person1_ Ну, если тип `Person` является ** классом **, то геттер вернет ** ссылку ** в` Объект ** ** **. Затем этот объект будет мутирован. Частное поле `person1` является другой ссылкой на тот же объект. Но если «Лицо» было ** структурой **, то получатель возвращал ** значение **, которое было бы ** копией ** значения `person1`. Поэтому даже ваш первый код не будет работать, если `Person` был значением типа. – 2012-11-19 14:26:08

ответ

4

Каждый раз, когда вы получаете доступ к своей собственности, Captin будет читать с диска. Но если вы измените имя свойства, оно не будет записываться на диск. Он будет записывать только на диск, если вы сделаете что-то вроде

public void SomeFunction() { 
    Person p = Captin; 
    p.name = "Hook"; 
    Captin = p; 
} 
1

Как @Joe отмечает, что он не будет записывать на диск. Я просто хотел добавить, что это потому, что вы используете только геттер, а не сеттер. Пример Джо использует оба.

На мой взгляд, это и очень плохое использование геттера и нарушает разделение проблем. У вас должен быть слой данных, который обрабатывает данные. Логика этого не должна быть в вашем бизнес-объекте.

+0

Меня больше всего интересует использование кешированных копий объектов – minty 2008-11-20 16:52:00

1

Редактор свойств будет вызываться только тогда, когда кто-то фактически назначает его напрямую.

Что касается вашего кода в порядке или нет: это вопрос документации.

Всякий раз, когда у вас есть свойство, которое возвращает что-то изменяемое, вы должны указать, будут ли какие-то мутации ему делать. Вы возвращаете копию своих «реальных» данных, или это реальные данные? Это происходит очень часто, когда свойство (или обычный метод) возвращает какую-то коллекцию - она ​​изменена? Что произойдет, если я изменю его?

Если вы задокументируете свое имущество, объяснив, что возвращенные данные являются просто копией, а изменения нигде не отражаются, это нормально. Если вы оставите это двусмысленным, тогда у вас появятся проблемы.

Неизменность снимает эти проблемы, конечно ...

1

Переменная класса типа, параметр, поле, возвращаемое значение, или другие подобные места хранения следует рассматривать как проведение «идентификатор объекта». Если какой-либо объект Foo имеет свойство типа Bar некоторого типа класса, которое поддерживается полем _Bar, а _Bar содержит «идентификатор объекта № 24601», то оператор Foo.Bar.Text = "George" будет вызывать setter Text на объекте # 24601 со значением «George» , Обратите внимание, что этот оператор не будет изменять объект Foo (его поле _Bar проведет «идентификатор объекта # 24601» до выполнения оператора и будет по-прежнему удерживать его после); это, скорее всего, повлияет на объект # 24601.

Хранилище структурного типа должно рассматриваться как содержащее содержимое всех его полей (как государственных, так и частных).Если Foo.Boz были свойством типа Rectangle (который является структурой) и фонового поля _Boz, то доступ к Foo.Boz создаст новый временный экземпляр типа Rectangle, все поля которого будут скопированы из полей Foo._Boz. Попытка прочитать Foo.Boz.X скопировала бы все поля _Boz во временный экземпляр, а затем поле доступа X этого экземпляра.

Обратите внимание, что некоторые действительно старые и злые компиляторы C# интерпретируют код Foo.Boz.X = 5; как Rectangle temp; temp.X = 5;, отбрасывая полученное значение темпа, но не выдавая никакого предупреждения. Такое поведение компилятора побудило некоторых людей объявить, что структуры должны быть «неизменными», чтобы гарантировать, что такой код будет генерировать ошибку компилятора, а не создавать фиктивное поведение. К сожалению, эта вера сохраняется и по сей день, несмотря на то, что любой достойный компилятор запретил бы такой код, даже если X был изменчивым полем.

Обратите внимание, что правильный идиоматических способ обновить свойство изменяемого типа структуры является:

 
    Rectangle temp = MyListOFRectangles[5]; 
    temp.X = 5; 
    MyListOFRectangles[5] = temp; 

Если Rectangle известно иметь общественное целое поле с именем X и MyListOfRectangles является List<Rectangle>, один Безразлично» t знать о любом из других свойств, конструкторов и т. д. Rectangle, чтобы знать, что вышеуказанный код изменит MyListOfRectangles[5].X, но не повлияет на какое-либо другое имущество MyListOfRectangles[5], а также на любую собственность MyListOfRectangles[4]. Хороший, ясный и легкий. Структуры раскрытого поля допускают частичное редактирование значений способом, который является ясным и последовательным, в отличие от любого другого типа данных.

+0

Upvoted. Таким образом, вы считаете, что это нормально писать изменяемые структуры (учитывая, что компилятор будет знать, что он не может мутировать непосредственный результат вызова метода, как в `GetSomeStructValue(). Name =« Hook »;` который не будет компилироваться)? – 2012-11-19 14:33:59

Смежные вопросы