A konstans
Ha azt szeretnénk, hogy egy primitív (beépített típusú) vagy enum változó értéke ne tudjon módosulni, hanem az egész programra nézve ugyanaz legyen mindig, akkor azt a változót meg kell jelölni a const kulcsszóval.
Bizonyos szinten ellentmondás az, hogy egy változó konstans. Most változik az értéke vagy sem?
Ez viszont csak a “változó” / “variable” elnevezés miatt van így. Pontosabban leírná a fogalmat, ha úgy hívnánk a változót, hogy “Nevesített objektum tároló”. Ennek azonban sajnos nem olyan jó a csengése. Ezért marad a változó, ami csak akkor hangzik furán ha éppen az konstans.
(Lokális változók és field-ek is lehetnek konstansok.)
Egy konstans változó csak egyszer van eltárolva a memóriában szemben a normál mezőkkel, amik annyiszor léteznek, ahány példány létezik az őket tartalmazó összetett típusból.
Vegyük a következő példát:
A fenti kód leír egy Person (személy) osztályt. Minden személynek van egy neve és egy kora.
Mivel 5 személyt hoztam létre ebből az osztályból, így 5 különböző kor változó létezik a memóriában. Minden személyhez egy.
Azonban a nagykorúság korhatára egy fix érték, mindenkire ugyanúgy igaz. Nem érdemes többször eltárolni és nem tartozik csak egy személyhez. Ezért osztályon kívülről nem az objektum-on, hanem az osztály nevén keresztül tudunk hivatkozni rá:
// Normál mező:
int ageOfLisa = person4.age; // Hivatkozás egy példányon keresztül
// Konstans:
int limitAge = Person.adulthoodAgeLimit; // Hivatkozás az osztály nevén keresztülMindebben a konstans “változó” nagyban hasonlít egy statikus tagra.
Látsd: Statikus tagok és osztályok
readonly: A csak olvasható mező
Konstansokat csak a C# beépített (primitív) típusaiból és enum-okból tudunk létrehozni.
Minden egyéb típusból hasonló célra érdemes lehet egy readonly, azaz csak olvasható mezőt használni. Ezen fajta változónak csak egyszer az objektum létrejöttekor adhatunk értéket, ami aztán nem változhat. Ezt tehetjük közvetlen értékadással (a deklarációval egy sorban) vagy konstruktorral:
// Létrehozok két readonly vektort,
// amik egység hosszúak és 45 fokos szöget zárnak be minden tengellyel:
// Értékadás egyből deklarációvan egy sorban.
readonly Vector2 diagonal2 = new (1/Mathf.Sqrt(2), 1/Mathf.Sqrt(2));
// Értékadás konstruktorral:
readonly Vector3 diagonal3;
TestClass() // Konstruktor
{
float d = 1 / Mathf.Sqrt(3);
diagonal3 = new (d, d, d);
}Gyakran a readonly változó egyben static is. Ekkor gyakorlatilag konstansként viselkedik.
Lehetséges statikus osztályokban statikus konstruktort is írni, ami egyszer fog lefutni mielőtt először használnánk az osztályt. Ebben beállíthatjuk az ilyen elemek értékeit. Pl.:
static class MyMath
{
public static readonly Vector2 diagonal2;
public static readonly Vector3 diagonal3;
MyMath() // statikus konstruktor
{
float d2 = 1 / Mathf.Sqrt(2);
diagonal2 = new (d3, d3);
float d3 = 1 / Mathf.Sqrt(3);
diagonal3 = new (d3, d3, d3);
}
}