In ziua de azi aproape toata lumea foloseste clase. Cand aude cineva de struct, se uita la tine ciudat, de parca ai venit din evul mediu. In unele cazuri o structura este o optiune mult mai buna decat o clasa, dar nu despre asta o sa discutam astazi. O sa discutam putin despre o eroare pe care multa lume o primeste cand lucreaza cu struct.
O structura poate sa contina constante, field-uri, propietati, operatori, evenimente, index-uri etc. Aceasta se poate folosii 'oarecum' ca si o clasa, dar este un VALUE TYPE pana la moarte.
Ce inseamna asta? Nu se poate sa mosteneasca o alta structura, nu poate sa fie derivata, nu poate sa contina valoarea NULL etc. Pentru o definitie completa va rog sa va uitati la urmatoarea adresa http://msdn.microsoft.com/en-us/library/s1ax56ch%28v=vs.71%29.aspx
Ce ne intereseaza pe noi cel mai mult este ca structurile sunt "IMUTABILE" din anumite puncte de vedere - odata ce au fost create, starea lor interna nu poate sa fie schimbata. Nici o valoare din interiorul unei structuri nu poate sa fie modificata. De fapt, ce se intampla in spate cand facem o noua "referinta" la structura, este sa se creeze o noua copie a acesteia. Cand referim o alta structura se copiaza valoarea s-a si nu referinta.
Din aceasta cauza orice modificare pe care noi o facem la structura, se va face pe copia ei si nu pe structura insasi. Daca dorim sa facem acest lucru atunci este nevoie sa inlocuim toata structura, creand una noua.
Din aceasta cauza un field se poate initializa o singura data, in momentul in care construim structura. Orice modificare a unui field dupa acest moment nu o sa mai poata sa fie facuta.
Nu trebuie sa uitam ca nu are rost sa ne definim un contructur pentru o structura - care sa itializeze campurile cu valoare defapt, deoarece by default o sa avem mereu unul care va face acest lucru(pentru fiecare camp in parte).
Enjoy!
Cannot modify the return value of XXX because it is not a variableCod sursa:
struct Foo
{
public int Value { get; set; }
}
class FooContainer
{
public FooContainer()
{
Foo = new Foo() {Value = 1};
}
public Foo Foo { get; private set; }
}
...
FooContainer fooContainer=new FooContainer();
fooContainer.Foo.Value = 2; // !!!
Cauza la aceasta eroare nu este limbajul, Visual Studio sau orice alt dezvoltator care a lucrat la proiect. Este vina celui care vrea schimbe valoarea unei date dintr-o structura.O structura poate sa contina constante, field-uri, propietati, operatori, evenimente, index-uri etc. Aceasta se poate folosii 'oarecum' ca si o clasa, dar este un VALUE TYPE pana la moarte.
Ce inseamna asta? Nu se poate sa mosteneasca o alta structura, nu poate sa fie derivata, nu poate sa contina valoarea NULL etc. Pentru o definitie completa va rog sa va uitati la urmatoarea adresa http://msdn.microsoft.com/en-us/library/s1ax56ch%28v=vs.71%29.aspx
Ce ne intereseaza pe noi cel mai mult este ca structurile sunt "IMUTABILE" din anumite puncte de vedere - odata ce au fost create, starea lor interna nu poate sa fie schimbata. Nici o valoare din interiorul unei structuri nu poate sa fie modificata. De fapt, ce se intampla in spate cand facem o noua "referinta" la structura, este sa se creeze o noua copie a acesteia. Cand referim o alta structura se copiaza valoarea s-a si nu referinta.
Din aceasta cauza orice modificare pe care noi o facem la structura, se va face pe copia ei si nu pe structura insasi. Daca dorim sa facem acest lucru atunci este nevoie sa inlocuim toata structura, creand una noua.
Din aceasta cauza un field se poate initializa o singura data, in momentul in care construim structura. Orice modificare a unui field dupa acest moment nu o sa mai poata sa fie facuta.
Nu trebuie sa uitam ca nu are rost sa ne definim un contructur pentru o structura - care sa itializeze campurile cu valoare defapt, deoarece by default o sa avem mereu unul care va face acest lucru(pentru fiecare camp in parte).
Enjoy!
//...
ReplyDeleteFooContainer fooContainer = new FooContainer();
Foo foo = fooContainer.Foo;
foo.Value = 2;
/// atentie doar ce faci cu foo mai departe, deoarece fooContainer.Foo (originalul) nu va reflecta modificarea ta - Foo fiind un value type
/// restrictia de a modifica un value type returnat de o proprietate sau metoda vine tocmai din faptul ca iti returneaza o copie de care trebuie sa ai grija explicit atunci cand o modifici.
/// Imutabilitatea nu are legatura cu asta iar value type-urile nu sunt imutabile prin definitie. exemplul de mai sus o demonstreaza.
BTW, foarte fain topicul!
Din cauza asta am pus cu ghilimele imutabil. In exemplul dat mai sus se comporta din unele puncte de vedere ca un obiect imutabil.
ReplyDeleteCauza e si limbajul oarecum, fiindca struct in C# e alt animal decat in C++ (unde e prea putin diferit fata de un class )- cine a invatat mai intai C++ nu se asteapta la multe din "surprizele" din C# (care au logica lor, da' ...) - probabil mai tii minte discutia: http://ronua.ro/CS/forums/t/8066.aspx :)
ReplyDelete