Не декларирайте променливи референтни типове само за четене - защо не?

Четох този въпрос и няколко други отговора и докато разбирам разликата между промяната на препратката и промяната на състоянието на текущия екземпляр, не съм сигурен защо това означава, че не трябва да го маркирам само за четене. Дали това е така, защото маркирането на нещо като само за четене казва на компилатора нещо специално за екземпляра и така той може след това да го третира като нишково безопасно, когато всъщност може да не е?

Вероятно има ситуации, в които не искам екземплярът да може да се променя, но нямам нищо против, ако състоянието на екземпляра е променено (може би единичен. /аз се подготвям за пламъци) Какви са последствията от маркирането на екземпляра само за четене, ако искам това?


person Sam Holder    schedule 03.03.2010    source източник


Отговори (4)


Няма (базирани по време на изпълнение/околна среда) последствия. Компилаторът няма да откачи, вашето време за изпълнение няма да експлодира и като цяло всичко ще бъде наред.

Само FxCop (инструмент за статичен анализ, който някои хора използват) има предупреждение за това. Причините за предупреждението са обяснени в нишката, към която сте се свързали (семантично може да не е ясно, че обектът всъщност не е „само за четене“, а само че променливата не може да бъде „преназначена“).

Лично аз не съм съгласен с правилото, така че просто бих го деактивирал (ако използвате FxCop и ви засяга).

person Noon Silk    schedule 03.03.2010
comment
благодаря, това е, което исках да знам, просто исках да съм сигурен, че времето за изпълнение няма да направи никакви предположения за този член въз основа на факта, че е маркиран като само за четене - person Sam Holder; 03.03.2010
comment
Четейки статията, свързана от Ерик, не смятам, че трябва да пренебрегвам това правило. Декларацията ReadOnly може да направи изпълнението на поведение, доста различно от това, което очаквате. - person Rafa; 14.03.2014
comment
@Rafa: Ако поле, което идентифицира променлив обект от клас, е маркирано с readonly, тогава копие на препратката ще предостави изглед на живо на състоянието, капсулирано от полето. Ако полето не е отбелязано с readonly, тогава копие на препратката може да се отдели от състоянието, капсулирано от полето. Това, че някои хора не знаят какво означава readonly, когато се прилага към препратка към променлив обект, не означава, че действителното му значение не е полезно. - person supercat; 18.03.2015

Интересен свързан момент: променливите структури само за четене са лоша идея поради ситуации като тази:

http://ericlippert.com/2008/05/14/mutating-readonly-structs/

Повечето от хората, на които показах този код, не са в състояние да предвидят правилно изхода му.

Променливите структури само за четене имат проблема, че хората си мислят, че ги мутират, но всъщност те мутират копие.

Променливите референтни типове само за четене имат обратния проблем. Хората си мислят, че са дълбоко неизменни, но всъщност те са само плитко неизменни.

person Eric Lippert    schedule 03.03.2010

Мисля, че въпросът е, че може да е подвеждащо - непредпазлив читател може да предположи, че променливата само за четене всъщност е константа, което не би било.

Бих го третирал повече като предложение, отколкото правило - със сигурност има случаи, в които може да е разумно, но трябва да се използва внимателно. (По-специално, бих бил нервен, ако променливото състояние беше изложено на външния свят.)

person Jon Skeet    schedule 03.03.2010

Тези два типа декларации са валидни и полезни, въпреки че означават различни неща:

  • постоянна препратка към променлив обект.
  • променлива препратка към постоянен обект.

Ако наистина искате постоянна препратка към променлив обект, изглежда неприемливо да бъдете принудени да се задоволявате с променлива препратка по някаква причина, да не говорим за лоша. В многопоточното програмиране постоянната препратка може да ви спести необходимостта от синхронизиране на обекта-собственик (все още трябва да синхронизирате променливия обект чрез препратката, но това е по-фино заключване).

Непредпазливите читатели вероятно са и непредпазливи писатели - не мога да направя много за тях, освен:

const SourceRepository cvs = new ReadOnlyRepository(...);

C++ има средство за налагане на постоянен указател към постоянен обект (препратките са малко по-различни в C++):

Object const* const constantPointerToConstantObject = ...;

Това е една от малкото функции на C++, които ми липсват в C#/Java.

D има още по-добра ключова дума (immutable), която налага транзитивна неизменност. D's immutable позволява на компилатора да прави оптимизации, за които се притеснявате, и гарантира безопасност. D също има const за нетранзитивна константност, което предполага, че както транзитивните, така и нетранзитивните форми са независимо полезни.

person richj    schedule 31.08.2010