Kan du ha en klasse i en struct?

stemmer
23

Er det mulig i C # for å ha en Struct med et medlem variabel som er en klasse type? Hvis ja, hvor kommer informasjonen bli lagret, på Stack, haugen, eller begge deler?

Publisert på 16/09/2008 klokken 01:45
kilden bruker
På andre språk...                            


4 svar

stemmer
21

Ja det kan du. Pekeren til klassen medlemsvariabel er lagret på stabelen med resten av struct verdier, og den klasse forekomst dataene lagres på haugen.

Structs kan også inneholde klassedefinisjoner for eksempel medlemmer (indre klasser).

Her er noen virkelig ubrukelig kode som minst kompilerer og kjører for å vise at det er mulig:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStr m = new MyStr();
            m.Foo();

            MyStr.MyStrInner mi = new MyStr.MyStrInner();
            mi.Bar();

            Console.ReadLine();
        }
    }

    public class Myclass
    {
        public int a;
    }

    struct MyStr
    {
        Myclass mc;

        public void Foo()
        {
            mc = new Myclass();
            mc.a = 1;
        }

        public class MyStrInner
        {
            string x = "abc";

            public string Bar()
            {
                return x;
            }
        }
    }
}
Svarte 16/09/2008 kl. 01:53
kilden bruker

stemmer
10

Klassen innhold blir lagret på haugen.

En henvisning til den klasse (som er nesten det samme som en peker) blir lagret sammen med den struct innhold. Hvor struct innholdet blir lagret avhenger av om det er en lokal variabel, metodeparameter, eller et medlem av en klasse, og hvorvidt det har blitt pakket, eller fanget av en lukkeanordning.

Svarte 23/07/2011 kl. 15:53
kilden bruker

stemmer
3

Hvis ett av feltene i en struct er en klasse type, vil det feltet enten holde identiteten av en klasse objekt eller annet en null referece. Dersom klassen objektet er uforanderlig (for eksempel string), lagring av identiteten effektivt vil også lagre innholdet. Hvis klassen aktuelle objektet er foranderlig, men lagring av identitet vil være et effektivt middel for å lagre innholdet hvis og bare hvis referansen aldri vil falle i hendene på noen kode som kan mutere den når den er lagret i feltet .

Generelt bør man unngå lagring foranderlig klassetyper innenfor en struktur med mindre en av to situasjoner gjelder:

  1. Hva man er interessert i er faktisk identiteten til klasse objektet snarere enn dens innhold. For eksempel kan man definere en 'FormerControlBounds` struktur som holder feltene av type Control` og' Rectangle`, og representerer den `Bounds` at kontrollen hadde på et eller annet tidspunkt, for det formål å være i stand til senere å gjenopprette kontrollen til sin tidligere stilling. Formålet med `Control` feltet ikke ville være å holde en kopi av kontrollens tilstand, men snarere å identifisere kontroll hvis posisjon skal gjenopprettes. Vanligvis struct bør unngå å få tilgang til noen foranderlig medlemmer av objektet den inneholder en referanse, unntatt i de tilfeller hvor det er klart at en slik adgang er henviser til den aktuelle foranderlig tilstand av det aktuelle objektet (for eksempel i en 'CaptureControlPosition` eller' RestoreControlToCapturedPosition` metode, eller en 'ControlHasMoved` egenskap).
  2. Feltet er `private`, de eneste metodene som leser den gjøre det med det formål å undersøke dens egenskaper uten å utsette selve objektet det til utenfor kode, og de eneste metodene som skriver det vil skape et nytt objekt, utføre alle de mutasjoner som noen gang kommer til å skje med den, og deretter lagre en referanse til dette objektet. Man kan for eksempel lage en `struct` som oppførte seg omtrent som en matrise, men med verdi semantikk, ved å ha struct holde en rekke i en privat felt, og ved å ha alle forsøk på å skrive matrisen opprette en ny rekke med data fra den gamle, modifisere den nye matrise, og lagrer den modifiserte matrisen til dette feltet. Merk at selv om matrisen selv ville være en foranderlig typen, ville hver rekke forekomsten som noen gang ville bli lagret i feltet være effektivt uforanderlig, siden det aldri vil være tilgjengelig med en kode som kan mutere det.

Merk at scenario # 1 er ganske vanlig med generiske typer; for eksempel, er det svært vanlig å ha en ordbok som "verdier" er identiteten til foranderlig objekter; opplisting at ordboken vil returnere tilfeller av KeyValuePairhvis Valuefeltet mener at foranderlig type.

Scenario # 2 er mindre vanlig. Det er dessverre ingen måte å fortelle kompilatoren at konstruere andre enn eiendoms settere vil endre en struct metoder og bruken bør derfor forbudt i skrivebeskyttet sammenhenger; en kunne ha en struct som oppførte seg som en List<T>, men med verdi semantikk, og med en Addmetode, men et forsøk på å ringe Addpå en skrivebeskyttet struct eksempel vil generere falsk kode i stedet for en kompilator feil. Videre mutere metoder og eiendoms settere på slike structs vil vanligvis utføre heller dårlig. Slike structs kan være nyttige, er når de eksisterer som et uforanderlig hylster på en ellers foranderlig-klasse; hvis en slik struct aldri eske, vil ytelsen ofte være bedre enn en klasse. Hvis eske nøyaktig én gang (for eksempel ved å bli kastet til et grensesnitt type), vil ytelsen generelt være sammenlignbar med en klasse. Hvis eske gjentatte ganger, kan ytelsen være mye verre enn en klasse.

Svarte 09/08/2012 kl. 16:14
kilden bruker

stemmer
2

Det er nok ikke en anbefalt praksis å gjøre det: se http://msdn.microsoft.com/en-us/library/ms229017(VS.85).aspx

Referanse typer fordeles på haugen, og minnehåndtering håndteres av søppel kollektoren.

Verdi Typer fordeles på stakken eller inline og deallocated når de går ut av omfanget.

Generelt verdityper er billigere å tildele og allokere. Men hvis de brukes i situasjoner som krever en betydelig mengde av boksing og unboxing, utfører de dårlig i forhold til referansetyper.

Svarte 16/09/2008 kl. 02:12
kilden bruker

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