Automatiske Egenskaper og strukturer ikke bland?

stemmer
62

Sparker rundt noen små strukturer mens du svarer på dette innlegget , kom jeg over følgende uventet:

Følgende struktur, ved hjelp av en int feltet er helt lovlig:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Legal assignment.
    } 

    public int Size; 
}

Men følgende struktur, ved hjelp av en automatisk Eiendommen har ikke kompilere:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Compile-Time Error!
    } 

    public int Size{get; set;}
}

Feilen som ble returnert er The 'denne' objektet kan ikke brukes før alle sine felt er tildelt. Jeg vet at dette er standard prosedyre for en struct: kompet feltet for enhver eiendom må tilordnes direkte (og ikke via hotellets sett tilbehør) fra struct konstruktør.

En løsning er å bruke en eksplisitt backing felt:

struct MyStruct
{ 
    public MyStruct(int size)
    {
        _size = size;
    }

    private int _size;

    public int Size
    {
        get { return _size; }
        set { _size = value; }
    }
}

(Merk at VB.NET ikke ville ha dette problemet, fordi i VB.NET alle felter blir automatisk initialisert til 0 / null / false når første laget.)

Dette synes å være en uheldig begrensning ved bruk av automatiske eiendommer med structs i C #. Tenker konseptuelt, jeg lurte på om dette ikke ville være et rimelig sted for det å være et unntak som gjør at eiendommen sett tilbehør til å bli kalt i en struct konstruktør, i hvert fall for en automatisk eiendom?

Dette er et mindre problem, nesten en kant-sak, men jeg lurte på hva andre syntes om dette ...

Publisert på 07/01/2009 klokken 14:14
kilden bruker
På andre språk...                            


3 svar

stemmer
81

Fra C # 6 videre: dette er ikke lenger et problem


Becore C # 6, må du ringe standardkonstruktøren for at dette skal fungere:

public MyStruct(int size) : this()
{
    Size = size;
}

Et større problem her er at du har en foranderlig struct. Dette er aldri en god idé. Jeg ville gjøre det:

public int Size { get; private set; }

Ikke teknisk uforanderlig, men nær nok.

Med nyere versjoner av C #, kan du forbedre på dette:

public int Size { get; }

Dette kan nå bare tildeles i konstruktøren.

Svarte 07/01/2009 kl. 14:17
kilden bruker

stemmer
10

Du kan fikse dette ved først å kalle standardkonstruktør:

struct MyStruct 
{
    public MyStruct(int size) : this() 
    {
        this.Size = size; // <-- now works
    }

     public int Size { get; set; }
}
Svarte 07/01/2009 kl. 14:21
kilden bruker

stemmer
7

En annen obskur work-around på dette problemet er en flekket i den midlertidige Tupleklassen i Managed Utvidbarhet Framework (via Krzysztof Kozmic ):

public struct TempTuple<TFirst, TSecond>
{
    public TempTuple(TFirst first, TSecond second)
    {
        this = new TempTuple<TFirst, TSecond>(); // Kung fu!
        this.First = first;
        this.Second = second;
    }

    public TFirst First { get; private set; }
    public TSecond Second { get; private set; }

(Full kildekode fra CodePlex: Tuple.cs )

Jeg også oppmerksom på at dokumentasjonen for CS0188 har blitt oppdatert for å legge:

Hvis du ser denne feilen når du prøver å klargjøre en eiendom i en struct konstruktør, er løsningen å endre konstruktøren parameter for å angi støtte feltet i stedet for eiendommen selv. Auto-implementert egenskaper bør unngås i structs fordi de har ingen støtte felt, og derfor kan ikke initialiseres på noen måte fra konstruktøren.

Så jeg tar det å bety at den offisielle veiledningen er å bruke gammel stil eiendommer i dine structs når du kjører inn i dette problemet, som sannsynligvis er mindre obskure (og mer readible) enn noen av de to andre alternativene utforsket så langt.

Svarte 11/02/2009 kl. 05:50
kilden bruker

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