Sök…


Anmärkningar

Vanligtvis används en struct endast när prestanda är mycket viktigt. Eftersom värdetyper lever på bunten kan de nås mycket snabbare än klasser. Men stacken har mycket mindre utrymme än högen, så strukturer bör hållas små (Microsoft rekommenderar att struct tar upp mer än 16 byte).

En class är den mest använda typen (av dessa tre) i C #, och är i allmänhet vad du bör gå med först.

Ett enum används när du kan ha en tydligt definierad, tydlig lista över objekt som bara behöver definieras en gång (vid sammanställningstiden). Enums är användbara för programmerare som en lätt referens till något värde: istället för att definiera en lista med constant att jämföra med, kan du använda enum och få Intellisense-stöd för att se till att du inte använder ett felaktigt värde av misstag.

Strukturdefinition

Strukturer ärver från System.ValueType, är värdetyper och lever på stacken. När värdetyper skickas som en parameter, skickas de efter värde.

Struct MyStruct
{
    public int x;
    public int y;
}

Passerat med värde betyder att värdet på parametern kopieras för metoden, och eventuella ändringar som gjorts i parametern i metoden återspeglas inte utanför metoden. Tänk till exempel på följande kod, som kallar en metod med namnet AddNumbers in variablerna a och b , som är av typen int , som är en värdetyp.

int a = 5;
int b = 6;

AddNumbers(a,b);

public AddNumbers(int x, int y)
{
    int z = x + y; // z becomes 11
    x = x + 5; // now we changed x to be 10
    z = x + y; // now z becomes 16
} 

Även om vi lägger till 5 till x inne i metoden förblir värdet på a oförändrat, eftersom det är en värdetyp, och det betyder att x var en kopia av a värde, men inte faktiskt a .

Kom ihåg att värdetyper lever på bunten och skickas efter värde.

Klassdefinition

Klasser ärver från System.Object, är referenstyper och lever på högen. När referenstyper skickas som en parameter, skickas de genom referens.

public Class MyClass
{
    public int a;
    public int b;
}

Om du skickar en referens innebär att en referens till parametern skickas till metoden, och eventuella ändringar av parametern reflekteras utanför metoden när den kommer tillbaka, eftersom referensen är till exakt samma objekt i minnet . Låt oss använda samma exempel som tidigare, men vi "paketerar" int i en klass först.

MyClass instanceOfMyClass = new MyClass();
instanceOfMyClass.a = 5;
instanceOfMyClass.b = 6;

AddNumbers(instanceOfMyClass);

public AddNumbers(MyClass sample)
{
    int z = sample.a + sample.b; // z becomes 11
    sample.a = sample.a + 5; // now we changed a to be 10
    z = sample.a + sample.b; // now z becomes 16
} 

Den här gången, när vi ändrade sample.a till 10 , värdet av instanceOfMyClass.a ändras också, eftersom det antogs av referens. Vidarebefordrad av referens betyder att en referens (även ibland kallad en pekare ) till objektet skickades in i metoden i stället för en kopia av själva objektet.

Kom ihåg att referenstyper lever på högen och skickas som referens.

Enum Definition

Enum är en speciell klass. Nyckelordet enum berättar kompilatorn som den här klassen ärver från det abstrakta klassen System.Enum. Enums används för distinkta listor över objekt.

public enum MyEnum
{
    Monday = 1,
    Tuesday,
    Wednesday,
    //...
}

Du kan tänka på enum som ett bekvämt sätt att kartlägga konstanter till ett underliggande värde. Enumet som definieras ovan deklarerar värden för varje veckodag och börjar med 1 . Tuesday skulle då automatiskt kartläggas till 2 , Wednesday till 3 osv.

Som standard använder enums int som underliggande typ och börjar vid 0, men du kan använda vilken som helst av följande integrerade typer : byte, sbyte, short, ushort, int, uint, long, or ulong , och kan ange uttryckliga värden för valfri Artikel. Om vissa artiklar är specifikt specificerade, men andra inte, kommer varje objekt efter den senast definierade artikeln att ökas med 1.

Vi skulle använda detta exempel genom att kasta något annat värde till ett MyEnum så:

MyEnum instance = (MyEnum)3; // the variable named 'instance' gets a 
                             //value of MyEnum.Wednesday, which maps to 3.

int x = 2;
instance = (MyEnum)x; // now 'instance' has a value of MyEnum.Tuesday

En annan användbar, även om mer komplex, enum-typ kallas Flags . Genom att dekorera enum med attributet Flags kan du tilldela en variabel mer än ett värde åt gången. Observera att när du gör detta måste du definiera värden uttryckligen i bas 2-representation.

[Flags]
public enum MyEnum
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32, 
    Sunday = 64
}

Nu kan du jämföra mer än ett värde åt gången, antingen med bitvisa jämförelser eller, om du använder .NET 4.0 eller senare, den inbyggda Enum.HasFlag metoden.

MyEnum instance = MyEnum.Monday | MyEnum.Thursday; // instance now has a value of
                                                   // *both* Monday and Thursday,
                                                   // represented by (in binary) 0100. 

if (instance.HasFlag(MyEnum.Wednesday))
{
    // it doesn't, so this block is skipped
}
else if (instance.HasFlag(MyEnum.Thursday))
{
    // it does, so this block is executed
}

Eftersom klassen Enum underklassas från System.ValueType , behandlas den som en värdetyp och skickas efter värde, inte som referens. Basobjektet skapas på högen, men när du överför ett enumvärde till ett funktionssamtal, skjuts en kopia av värdet med den underliggande värdetypen för Enum (vanligtvis System.Int32) på bunten. Kompilatorn spårar kopplingen mellan detta värde och basobjektet som skapades på stacken. Se ValueType Class (System) (MSDN) för mer information.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow