C # - Hvordan kan jeg sørge for at alle mine strukturer er initialisert?

stemmer
6

Jeg skriver et program i C # som kommer til å gjøre omfattende beregninger. Alt går rundt grunnleggende struct - verdi. Det er i utgangspunktet dobbelt med noen ekstra parametre (nøyaktighet etc.) Det må være en struct, fordi det vil være for mange av dem er laget for å ha råd til haug tildeling. Nå må jeg sørge for at de alle er riktig initialisert. Jeg kan ikke erklære standard eksplisitt konstruktør, selv om jeg er gitt standard konstruktør som initialiserer alt med 0, noe som ikke gir mening i mitt domene.

Og det er ingen måte å nekte å skape en forekomst uten å kalle min konstruktør med parametre heller ...?

I utgangspunktet det jeg trenger er denne testen for å passere:

[Test]
public void HowDoesThisStructureInitializeByDefault()
{
   Value v = new Value(); - if this did not compile - it would have been ok!

   Assert.AreEqual(0, v.Val); - passes
   Assert.AreEqual(-1, v.Accuracy); - fails
}

Det ville være OK å kaste et unntak hvis ingen konstruktør er eksplisitt kalt og strukturen er fortsatt tilgjengelig, men sjekker at hele tiden ville ta for mye tid.

Jeg er nesten miste håpet nå, kan du hjelpe!

Publisert på 06/12/2008 klokken 18:39
kilden bruker
På andre språk...                            


5 svar

stemmer
4

Hvorfor kan du ikke definere en eksplisitt konstruktør? Dette er hva de er for . Dessuten, hvorfor tror du "ikke har råd haug tildeling"? Heap tildeling er veldig billig bedrifts språk. Hvordan har du testet denne antagelsen om at du ikke har råd til haug tildeling, eller faktisk at haug tildeling er dyrere i utgangspunktet?

(For en type som består av "en dobbel og flere parametere", jeg mistenker du opp i en størrelse der haug tildeling er faktisk billigere og mer effektiv)

I alle fall, du kan ikke hindre en bruker fra å ringe standard konstruktør på en verditype, hvis han ønsker det. Alt du kan gjøre er å sørge for at en bedre måte å initialisere verdien finnes, for eksempel en ikke-standardkonstruktør, eller hvis du ikke kan opprette en eller annen grunn, en funksjon som skaper og initialiserer din verditype når kalt.

Men selvfølgelig, du har ingen garantier for at folk faktisk kaller det.

Edit: Heap tildeling i .NET i hovedsak består av bare en enkel stabel skyvedrift. Det er det fine med administrerte (og søppel-samlet) språk. Kjøretiden anvender i alt vesentlig en stor stabel som sin haug, slik at hver allokering bare inkrementerer stakkpekeren litt (etter kontroll av at det er nok minne, selvfølgelig). Den søppel samler tar da vare på komprimering av minnet når det er nødvendig.

Så haugen tildeling seg selv er latterlig billig. Selvfølgelig kan den ekstra GC trykket sakte du ned igjen (Selv så vidt jeg vet, den tiden som kreves for en GC pass avhenger bare på antall levende objekt, ikke på de som skal GC'ed, så har utallige " døde" objekter som ligger rundt er kanskje ikke et stort problem), men på den annen side, er bunken tildeling ikke gratis heller. Verdi typer er vedtatt av verdi, så hver gang du passerer din type som en parameter til en funksjon, eller returnere den, må gjøres en kopi. Jeg vet ikke hvor stor verdi, men en dobbel 8 byte, og gitt at du har noen ekstra parametere, vil jeg anta at 32 bytes. Det kan være så stor at den ekstra kopiering nødvendig for valuetypes gjør det tregere enn om du hadde brukt haug tildeling. Kanskje.

Som du ser, det er fordeler å både verdi- og referanse-typer. Jeg kan ikke si hvilken som er raskere i ditt tilfelle, men hvis jeg var deg ville jeg være veldig forsiktig med å gjøre denne type forutsetninger. Hvis mulig, struktur koden slik at du kan veksle mellom en referanse- og valuetype gjennomføring, og se hva som fungerer best. Alternativt skrive mindre tester for å prøve å forutsi hvordan hver ville utføre i stor skala.

Svarte 06/12/2008 kl. 19:03
kilden bruker

stemmer
3

Struct felt er initialisert til null (eller null, eller generelt standard (T)).

Hvis du vil utgangsverdien Nøyaktighet å være -1, kan du gjennomføre Nøyaktighet eiendommen slik at når den underliggende feltet == 0, eiendommen returnerer -1.

En mulighet:

struct Value
{
  int _accuracyPlusOne;

  public int Accuracy
  { 
    get { return _accuracyPlusOne - 1; }
    get { _accuracyPlusOne= value + 1; }
  }
}
Svarte 06/12/2008 kl. 19:15
kilden bruker

stemmer
3

Du kan ikke bli kvitt den standardkonstruktør (Jon Skeet, selvfølgelig, svarte hvorfor veldig bra på Hvorfor kan jeg ikke definere en standardkonstruktør for en struct i .NET? ), Men du kan opprette en fabrikk klasse som lar deg å definere struktur verdier med riktig initialisert parametere. Du kan bruke enheten tester med mock / bekrefte å sørge for at når nye verdier skapes av koden de bruker fabrikken. Dette ville være en konvensjon som du vil trenge for å håndheve som kompilatoren ikke vil håndheve det for deg.

public static class StructFactory
{
    public static Value DefaultValue()
    {
         Value v = new Value();
         v.Value = 0.0;
         v.Accuracy = 15; /* digits */
         return v;
    }
}

...

Value v = StructFactory.DefaultValue();
Svarte 06/12/2008 kl. 19:10
kilden bruker

stemmer
2

Jeg tror ikke C # kan du lage standard konstruktører på verdityper. Det er flere spørsmål knyttet til problemet:

Det er en måte å gjøre det i IL, men initialisering arrays fortsatt vil ikke kalle disse konstruktører.

Svarte 06/12/2008 kl. 19:01
kilden bruker

stemmer
0

Er du håper å initial nøyaktigheten til -1 til en standard konstruktør? Jeg tror ikke du kan stoppe noen fra å bruke new Value(), men du kan legge til en konstruktør som lar deg bruke new Value(10)og har nøyaktigheten initialisert slik du ønsker.

Se MSDN side om [Struct Constructors] ( http://msdn.microsoft.com/en-us/library/aa288208(VS.71).aspx) .

Du kan alltid kaste et unntak i koden som bruker strukturen hvis du støter på en nøyaktighet på 0 (hvis den verdien aldri er fornuftig!).

Svarte 06/12/2008 kl. 19:00
kilden bruker

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