Hvorfor må jeg tilbakestille alle felt i min C # struct med en ikke-standardkonstruktør?

stemmer
12

Jeg vil gjerne prøve denne koden:

public struct Direction
{
   private int _azimuth;

   public int Azimuth
   {
     get { return _azimuth; }
     set { _azimuth = value; }
   }       

   public Direction(int azimuth)
   { 
      Azimuth = azimuth
   } 
}

Men det mislykkes på kompilering, jeg forstår at struct trenger å init alle sine felt. men jeg prøver å forstå hva som skjer under CLR \ IL hetter. hvorfor det må alle feltene før noen annen metode \ eiendom \ dette etc.

Takk.

Publisert på 06/04/2009 klokken 12:40
kilden bruker
På andre språk...                            


6 svar

stemmer
9

Verdi Typer opprettes på stakken (med mindre nestet i en referansetype) Det er noe med felt / steder på stakken som CLR ikke kan garantere at de vil bli nullet ut (i motsetning til felt / steder på greid haug som er garantert til å bli nullet ut). Derfor må de skrives til før de blir lest. Ellers er det et sikkerhetshull.

Struct standard ctor (som tar ingen parametere og som du ikke har lov til å eksplisitt angi) nuller ut alle felt av en struct og dermed kan du bruke en struct etter at du gjør.

new BimonthlyPairStruct()

Men når du implementere parametriseres ctor, du må sørge for at alle feltene er initialisert - som er nødvendig for CLR å passere koden din så trygg / bekreftet .

Se også: CLR via C # andre Ed - Pg 188

Svarte 25/04/2009 kl. 14:02
kilden bruker

stemmer
5

Jeg har akkurat funnet en forklaring på MSDN forum som sier at denne regelen ikke håndheves fordi nullstilling ut minne hoppes hvis du bruker en ingen standardkonstruktør. Så du må gi initialisering verdier for alle felt for å unngå noen av feltene inneholder tilfeldige verdier. Du oppnå dette enkelt å kalle parameteren mindre standardkonstruktør, men på bekostning av initialisering noen felt to ganger.

Jeg kan ikke si om denne forklaringen er riktig, men det høres fornuftig.

Når du definerer en ikke-standard initializer, C # krever at du sette alle felt fordi den hopper nullstilling av minnet, og lar deg initialisere det - ellers ville du må ha en dobbel initialisering ytelse hit. Hvis du ikke bryr deg om (svært liten) ytelse treffer du alltid kjeden et kall til: denne () initializer og da bare initial utvalgte områder.

Svarte 06/04/2009 kl. 13:02
kilden bruker

stemmer
5

Dette fungerer:

  public Direction(int azimuth)
  {
    _azimuth = azimuth;
  }

Fra spec:

Struct konstruktører er startet med den nye operatøren, men det betyr ikke at hukommelsen blir tildelt. I stedet for dynamisk allokering av et objekt, og å returnere en referanse til den, en struct konstruktør returnerer ganske enkelt struct verdi i seg selv (typisk i en midlertidig plassering på stabelen), og denne verdien blir deretter kopiert etter behov.

I utgangspunktet må kompilatoren se at hvert felt blir initialisert i konstruktøren slik at den kan kopiere disse verdiene, og det er ikke villig til å undersøke samtaler til funksjoner eller egenskaper.

Svarte 06/04/2009 kl. 12:58
kilden bruker

stemmer
5

Dette er fordi structs er hentet fra System.ValueType og ikke System.Object, implementerer System.ValueType standard constructur som du cannnot overstyre denne standard konstruktør initialiserer alle feltene i struct med standardverdien. Så hvis du gjennomfører noen parameter contructor i klassen må du også t0 sikre at du påberope system.ValueType standard konst. Og for å svare på hvorfor det er behov for å init all sin verdi dette er fordi verdien blir lagret i bunken minne.

Svarte 06/04/2009 kl. 12:57
kilden bruker

stemmer
2
public struct Direction
{
    public int Azimuth { get; private set; }

    public Direction(int azimuth) : this()
    {
        Azimuth = azimuth;
    }
}
Svarte 06/04/2009 kl. 12:42
kilden bruker

stemmer
-1

Du må initial feltet, og ikke via eiendommen.

Svarte 06/04/2009 kl. 12:42
kilden bruker

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