Hvordan du angir hva som standardtilstanden av en avledet struct bør være i C #?

stemmer
4

Jeg har sett ulike spørsmål på SO om ikke å være i stand til å bruke parameterless konstruktører eller ikke sette felt initializers, men jeg tror spørsmålet mitt slags går et skritt utover det.

Hva jeg ønsker å vite er, hvordan ville jeg gå om å sette opp standard verdien av en struct jeg trenger å definere? Sier jeg gjør en taxid struct, og standardverdien må være 999-99-9999 uansett grunn. Dette er allerede gjort med andre structs i .NET, nemlig Datetime. Hver gang du deklarerer en Datetime verdien umiddelbart satt til 1 januar 0001 00:00. Hvorfor det blir satt til denne verdien og ikke 0/0/0000 00: 00: 0000 AM? Det må være noe som skjer bak kulissene som gjør verdien faktisk gjøre fornuftig på sitt default, selv gitt de begrensninger satt på oss av C # med hensyn til structs.

Publisert på 07/04/2009 klokken 18:25
kilden bruker
På andre språk...                            


5 svar

stemmer
7

Generelt bør dette unngås. Hvis du trenger å kreve en god, standard sak som vil kreve bygging, bør du vurdere å bytte til en klasse.

En av de viktigste design retningslinjer for structs er: Gjør at en tilstand hvor all forekomst av data er satt til null, falsk eller null (som det passer) er gyldig.

For detaljer, se design retningslinjer .


Jeg har nettopp sett denne delen opp i retningslinjer for design andre utgave, og de har et eksempel i detalj dit ved hjelp av egenskaper og ikke-konvensjonelle styringer for å omgå dette, også. Det grunnleggende konseptet var å lagre verdien privat på en måte som 0 er "god standard", og gjøre noen form for trans i hver eiendom og metode overstyring (inkludert toString). I deres tilfelle, de brukte et positivt heltall som et eksempel, og lagre alltid curVal-1 i den private elementet, slik at standardverdien (0) blir behandlet som en verdi på 1. De tilsatt en konstruktør med en int val, og lagre verdi-en innvendig, etc.

Dette virker som en mye skjult, uventede overhead, selv om - så jeg personlig likevel anbefale (og bruke) en klasse i dette tilfellet.

--- Edit svar på kommentarer ---

Datetime, som eksempel, er måten det er fordi 0 == 1/1/0001 ved midnatt. Dato og tid bruker en enkelt, ULONG å representere flått fra 1/1/0001. Det er derfor ( herfra ):

"The Datetime verditype representerer datoer og klokkeslett med verdier fra 12:00:00 midnatt, 1. januar 0001 Anno Domini (Common Era) gjennom 23:59:59, 31. desember 9999 AD (CE)"

Dette er hele spekteret av ULONG i flått. En "0" i struct av Datetime behandles som 1/1/0001 når du konverterer til en streng - verdiene er ikke 1 + 1 + .... - det er en enkelt 0.

Svarte 07/04/2009 kl. 18:33
kilden bruker

stemmer
3

Hver gang du deklarerer en Datetime verdien umiddelbart satt til 1 januar 0001 00:00. Hvorfor det blir satt til denne verdien og ikke 0/0/0000 00: 00: 0000 AM? Det må være noe som skjer bak kulissene som gjør verdien faktisk gjøre "fornuftig" på sitt "default", selv gitt de begrensninger satt på oss av C # med hensyn til structs.

Mer sannsynlig er det implisitt initialiserer en flått-feltet til default(int)= 0 og 0 flått betyr DateTime.MinValuenår du går for å få verdien.

Svarte 07/04/2009 kl. 18:32
kilden bruker

stemmer
2

Ingenting skummel som skjer. Den interne representasjon av en Datetime er antallet 100 nanosekund "ticks" siden 12:00:00 midnatt, 1. januar 0001 Anno Domini. Når Datetime er opprettet, er flåtten teller null. Hvis du ser på Datetime med ILDASM, vil du se det er litt mer komplisert enn det, men du skjønner poenget. :)

Svarte 07/04/2009 kl. 18:49
kilden bruker

stemmer
0

Bare for fullstendighet:

Verdityper i C # (inkludert arrays, structs, enums) er alltid initialisert til alle nuller. Referansetyper er også i utgangspunktet null, bedre kjent som null.

Ved enums, er null standardverdien, og er alltid en mulig verdi selv om det ikke er en definert i enum. Personlig, jeg vanligvis definerer 0 Ingen, Tom, Ukjent eller noe lignende:

enum MyEnum { A = 1, B = 2, C = 3 };
// ...
MyEnum value = new MyEnum(); // value has a nameless 0

Ved matriser, hvis det er en rekke referansetyper, de er alle i utgangspunktet null(som du kan tenke på som en peker til adresse 0). Hvis det er en rekke verdityper, de er alle i utgangspunktet null eller tilsvarende (se andre svar om DateTime.Ticksog hvorfor en "nullet" Datetime er lik 1/1/0001 0:00).

Kommer tilbake til structs: det samme gjelder. De vil alltid ha en standard parameterless konstruktør og du kan ikke unngå dette. Alle verdi typen medlemmer vil i utgangspunktet være null (eller tilsvarende), og alle referanse typen medlemmer vil være null. Tenk om int, kort, desimal, røye, Datetime (ahem), Timespan, størrelse, Point, rektangel, farge, Guid ... de er alle initialisert til alle nuller.

Svarte 07/04/2009 kl. 19:29
kilden bruker

stemmer
0

Du kan ikke erklære en standard konstruktør i en C # struct. Du kan simulere dette problemet ved å opprette et privat felt og skrive en eiendom for å gå tilbake standardverdien hvis det er 1/1/1

Svarte 07/04/2009 kl. 18:28
kilden bruker

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