Uforanderlighet structs

stemmer
31

Mulig Duplicate:
Hvorfor er foranderlig structs onde?

Jeg leste det i mange steder inkludert her at det er bedre å gjøre structs som uforanderlig.

Hva er årsaken bak dette? Jeg ser mange Microsoft-laget structs som er foranderlig, som de i XNA. Sannsynligvis er det mange flere i BCL.

Hva er fordeler og ulemper med å ikke følge disse retningslinjene?

Publisert på 03/03/2009 klokken 22:42
kilden bruker
På andre språk...                            


9 svar

stemmer
43

Structs skal representere verdier . Verdier endres ikke. Tallet 12 er evig.

Men vurdere:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

Nå foo.Bar og foo2.Bar er annerledes, noe som ofte uventet. Spesielt i situasjoner som egenskaper (heldigvis kompilatoren gjenkjenne denne). Men også samlinger etc; hvordan kan du noensinne mutere dem fornuftig?

Tap av data er altfor lett med foranderlig structs.

Svarte 03/03/2009 kl. 22:46
kilden bruker

stemmer
17

Det store minuset er at ting ikke oppfører seg hvordan du forventer at de skal - særlig hvis mutability kommer fra en blanding av direkte verdi og en referansetype i den.

For å være ærlig, jeg kan ikke huske av toppen av hodet mitt alle de rare problemer jeg har sett folk kommer opp med i nyhetsgrupper når de har brukt foranderlig structs - men disse grunnene sikkert finnes. Foranderlig structs forårsake problemer. Hold deg unna.

EDIT: Jeg har nettopp funnet en e-post jeg skrev for en stund siden om dette emnet. Det utdyper bare litt:

  • Det er filosofisk feil: en struct skal representere en slags grunnleggende verdi. De er i utgangspunktet uforanderlig. Du får ikke til å endre nummer 5. Du kan endre verdien til en variabel 5-6, men du trenger ikke logisk gjøre en endring i selve verdien.

  • Det er praktisk talt et problem: det skaper mange rare situasjoner. Det er spesielt ille hvis det er foranderlig via et grensesnitt. Deretter kan du begynne å endre eske verdier. Æsj. Jeg har sett mange nyhetsgrupper innlegg som skyldes mennesker som prøver å bruke foranderlig structs og kjører inn spørsmål. Jeg så en veldig merkelig LINQ eksempel som var sviktende grunn List<T>.Enumeratorer en struct, for eksempel.

Svarte 03/03/2009 kl. 22:47
kilden bruker

stemmer
10

Jeg bruker foranderlig structs ofte i min (ytelse kritisk) prosjekt - og jeg ikke får problemer, fordi jeg forstår konsekvensene av kopi semantikk. Så vidt jeg kan fortelle, de viktigste grunnen til at folk argumentere uforanderlige structs er slik at folk som ikke forstår konsekvensene ikke kan komme seg i trøbbel.

Det er ikke så forferdelig ting - men vi er i fare nå for det blir "evangeliets sannhet", når det faktisk det er tider hvor det er legitimt det beste alternativet for å gjøre en struct foranderlig. Som med alle ting, det finnes unntak fra regelen.

Svarte 16/02/2011 kl. 13:18
kilden bruker

stemmer
5

Du har bedt om fordeler og ulemper med ikke å følge retningslinjene som structs skal være uforanderlig.

Cons: Cons er godt dekket i eksisterende svar, og de fleste problemene som beskrives er på grunn av samme årsak - uventet atferd på grunn av structs' verdi semantikk .

Pros: Den største pro for å bruke foranderlig structs kan være ytelse . Selvsagt kommer dette rådet med alle de vanlige advarsler om optimaliseringer: sørge for at en del av koden din være optimalisert og sørge for at eventuelle endringer faktisk optimalisere kode ytelse via profilering.

For en utmerket artikkel som handler om når du kanskje vil bruke foranderlig structs, se Rico Mariani sin ytelse Quiz på verdibasert programmering (eller mer spesifikt, svarene ).

Svarte 24/01/2011 kl. 23:21
kilden bruker

stemmer
5

Den tekniske Årsaken er at foranderlig structs synes å være i stand til å gjøre ting som de ikke faktisk gjøre. Siden utformingen gangs semantikk er de samme som referansetyper, blir dette forvirrende for utviklere. Denne koden:

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

Oppfører seg ganske forskjellig avhengig av om MySomethingen structeller en class. For meg er dette en overbevisende, men ikke den mest overbevisende grunn. Hvis du ser på DDD 's verdi Object , kan du se sammenhengen til hvordan structs bør behandles. En verdi objekt i DDD kan best representert som et verditype i Net (og derfor en struct). Fordi det har ingen identitet, kan det ikke endres.

Tenk på dette i form av noe som din adresse. Du kan "endre" din adresse, men adressen selv har ikke forandret seg. Faktisk, har du en ny adresse tildelt deg. Konseptuelt, dette fungerer, fordi hvis du faktisk endret adressen din, vil dine romkamerater må flytte også.

Svarte 03/03/2009 kl. 23:08
kilden bruker

stemmer
5

Det er ikke noe billigere å manipulere enn en foranderlig struct, som er grunnen til at du ofte se det på høy ytelse kode som grafikken rutiner.

Dessverre foranderlig structs ikke spiller godt med objekter og egenskaper, er det altfor lett å endre en kopi av en stuct stedet for struct selv. Dermed er de ikke egnet for de fleste av koden din.

PS For å unngå kostnadene ved å kopiere foranderlig structs, de er som regel lagret og bestått i arrays.

Svarte 03/03/2009 kl. 22:52
kilden bruker

stemmer
4

En struct bør generelt representerer en enkelt enhet av noe slag. Som sådan er det ikke mye mening å endre en av egenskapene til verdien, det er mer fornuftig å opprette en helt ny verdi hvis du vil ha en verdi som er annerledes liksom.

Semantikk blir enklere når du bruker uforanderlige structs, og du unngår fallgruvene som dette:

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

Resultatet er at struct i listen er ikke endret i det hele tatt. Uttrykket Intervall [0] kopierer verdien av struct fra listen, og du endrer egenskap av midlertidig verdi, men verdien blir aldri satt tilbake i listen.

Edit: Endret eksempel å bruke en liste i stedet for en matrise.

Svarte 03/03/2009 kl. 22:50
kilden bruker

stemmer
2

grunnen til at du bør gjøre structs uforanderlig, er at de er ValueTypes , noe som betyr at de er kopiert hver gang du passerer dem til en metode.

Så hvis, for eksempel, hadde du en eiendom som returnerte struct, endre verdien av et felt på den struct ville være verdiløs, fordi getter vil returnere en kopi av struct, snarere enn en referanse til struct. Jeg har sett dette gjort i kode, og det er ofte vanskelig å fange.

Hvis du designe din structs for uforanderlighet, hjelpe deg programmereren unngå disse feilene.

Svarte 03/03/2009 kl. 22:46
kilden bruker

stemmer
2

Når du kopierer structs rundt deg kopiere innholdet, så hvis du endrer en kopiert versjon av "originale" vil ikke bli oppdatert.

Dette er en kilde til feil, siden selv om du vet at du faller i fellen med å kopiere en struct (bare ved å sende den til en metode) og modifisere kopien.

Bare skjedde med meg en gang i forrige uke, holdt meg en time å lete etter en feil.

Holde structs uforanderlige hindrer at ...

Annet enn at du må sørge for at du har en veldig god grunn til å bruke structs i første omgang - "optimalisering" eller "jeg vil ha noe som tildeler raskt på stakken" teller ikke som et svar. Marshaling eller ting der du er avhengig av layout - ok, men du bør ikke vanligvis holde disse structs rundt på veldig lenge, er de verdier ikke stedene.

Svarte 03/03/2009 kl. 22:46
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more