Едно свойство не е нищо повече от капсулиране на Get
метод и/или Set
метод. CLR има метаданни, които показват, че определени методи трябва да се разглеждат като свойства, което означава, че компилаторите трябва да позволяват някои конструкции, които не биха позволили с методи. Например, ако X
е свойство за четене-запис на Foo
, компилаторът ще преведе Foo.X += 5
в Foo.SET_X_METHOD(Foo.GET_X_METHOD() + 5)
(въпреки че методите са именувани по различен начин и обикновено не са достъпни по име).
Въпреки че автоматичното свойство имплементира чифт get/set методи, които имат достъп до частно поле по такъв начин, че да се държат повече или по-малко като поле, от гледна точка на всеки код извън свойството, автоматичното свойство е двойка get/ задайте методи точно като всяко друго свойство. Следователно изявление като Foo.X = 5;
се превежда като Foo.SET_X_METHOD(5)
. Тъй като C# компилаторът просто вижда това като извикване на метод и тъй като методите не включват никакви метаданни, за да посочат какви полета четат или пишат, компилаторът ще забрани извикването на метода, освен ако не знае, че всяко поле на Foo
е записано.
Лично моят съвет би бил да избягвате използването на автосвойства със структурни типове. Автоматичните свойства имат смисъл с класовете, тъй като е възможно свойствата на класа да поддържат функции като известия за актуализиране. Дори ако ранните версии на клас не поддържат известия за актуализация, ако тези версии използват автоматично свойство, а не поле, ще означава, че бъдещите версии могат да добавят функции за известяване за актуализация, без да се налага потребителите на класа да бъдат преработени. Структурите обаче не могат смислено да поддържат повечето от типовете функции, които може да искате да добавите към свойства, подобни на поле.
Освен това разликите в производителността между полетата и свойствата са много по-големи при големите структури, отколкото при типовете класове. Всъщност голяма част от препоръките да се избягват големи структури са следствие от тази разлика. Големите структури всъщност могат да бъдат много ефективни, ако човек избягва ненужното им копиране. Дори ако някой има огромна структура HexDecet<HexDecet<HexDecet<Integer>>>
, където HexDecet<T>
съдържа открити полета F0
..F15
от тип T
, израз като Foo = MyThing.F3.F6.F9;
просто ще изисква прочитане на едно цяло число от MyThing
и съхраняването му в Foo
, въпреки че MyThing
би било огромно по стандарти за структура ( 4096 цели числа, заемащи 16K). Освен това човек може много лесно да актуализира този елемент, напр. MyThing.F3.F6.F9 += 26;
. За разлика от това, ако F0
..F15
бяха автоматични свойства, изразът Foo = MyThing.F3.F6.F9
ще изисква копиране на 1K данни от MyThing.F3
във временен (наречете го temp1
, след това 64 байта данни от temp1.F6
до temp2
), преди най-накрая да стигнете до четене на 4 байта на данни от temp2.F9
. Ик. Още по-лошо, опитът да се добави 26 към стойността в MyThing.F3.F6.F9
ще изисква нещо като var t1 = MyThing.F3; var t2 = t1.F6; t2.F9 += 26; t1.F6 = f2; MyThing.F3 = t1;
.
Много от дългогодишните оплаквания относно "променливи структурни типове" всъщност са оплаквания относно структурни типове със свойства за четене/запис. Просто заменете свойствата с полета и проблемите изчезват.
PS: Понякога може да е полезно да имате структура, чиито свойства имат достъп до обект от клас, към който има препратка. Например, би било хубаво да имаме версия на клас ArraySegment<T>
, която позволява да се каже Var foo[] = new int[100]; Var MyArrSeg = New ArraySegment<int>(foo, 25, 25); MyArrSeg[6] += 9;
и последният израз да добави девет към елемент (25+6) от foo
. В по-старите версии на C# можеше да се направи това. За съжаление, честото използване на автоматични свойства в рамката, където полетата биха били по-подходящи, доведе до широко разпространени оплаквания относно компилатора, който позволява безполезно извикване на настройки на свойства в структури само за четене; следователно извикването на който и да е инструмент за настройка на свойства на структура само за четене вече е забранено, независимо дали инструментът за настройка на свойства действително би променил полета на структурата. Ако хората просто се бяха въздържали да правят структури променливи чрез настройки на свойства (правейки полета директно достъпни, когато променливостта беше подходяща), компилаторите никога не би трябвало да прилагат това ограничение.
person
supercat
schedule
01.10.2012
protected
член не трябва да бъде разрешен вstruct
точно както не е разрешен вsealed class
. - person Jeppe Stig Nielsen   schedule 11.11.2017