Implicit típuskonverzió
Típuskonverzióról akkor beszélhetünk, ha a program szövegében adott ponton álló érték típusát meg kell változtatni valami oknál fogva.
A fordítóprogram pontosan ismeri minden értéknek a típusát, és azzal is tisztában van, hogy melyik típusra kellene megváltoztatni azt. Erre szükség lehet egy értékadó utasítás végrehajtása során a bal és a jobb oldal típusának egyeztetésekor, vagy esetleg valamely operátor végrehajtása előtt a két operandus típusait kell közös típusra hozni.
Az implicit típuskonverzióról akkor beszélünk, amikor a típusát-alakítást a fordítóprogram önállóan veszi észre és hajtja végre. Az implicit típuskonverzió során az új típusnak a neve nem szerepel az adott ponton a program szövegében, nincs ’látható’ nyoma.
Minden típushoz tartozik egy lista, hogy mely más típusokra lehet őt implicit módon átalakítani. Amennyiben a fordítóprogram által szükségesnek ítélt konverzió rajta van a listán – úgy a fordítóprogram azt beilleszti a kódba a megfelelő időpontban.
Az értékadó utasítás formailag ’azonosító = kifejezés’ alakú. Ennek segítségével állíthatjuk be, hogy az ’azonosító’ milyen értéket képviseljen a programunkban ezen időpillanattól kezdve.
Az azonosító általában valamilyen változó neve, de ezen értékadó utasítással állíthatjuk be a konstansok értékét is.
Az értékadó utasítás formailag ’azonosító = kifejezés’ alakú. Ennek segítségével állíthatjuk be a programunkban, hogy az ’azonosító’ milyen értéket képviseljen a programunkban ezen időpillanattól kezdve.
Az ’azonosító’, az értékadó utasítás jelének, az egyenlőség jelnek a bal oldalán szereplő név.
A bal oldalon álló kifejezést gyakran LHS-nek (Left Hand Side)-nak nevezi a szakirodalom.
Az LHS a gyakorlatban vagy (egy már korábban deklarált) valamely változó neve, vagy egy konstans neve lehet.
A változó, és a konstans deklarációjakor is meg kell adni annak típusát explicit módon. Ezt a típust nevezzük az LHS típusának.
Ezen típus minden esetben egyértelműen meghatározható.
Az értékadó utasítás formailag ’azonosító = kifejezés’ alakú. Ennek segítségével állíthatjuk be, hogy az ’azonosító’ milyen értéket képviseljen a programunkban ezen időpillanattól kezdve.
A ’kifejezés’ az értékadó utasítás jelének, az egyenlőség jelnek a jobb oldalán szereplő rész. Ezen részt gyakran RHS-nek (Right Hand Side)-nak nevezi a szakirodalom.
A kifejezés operátorokból és operandusokból épül fel. Az operátorok az adott operandusokon értelmezett műveleteket jelölnek, végrehajtásuk után egy-egy újabb értéket állítanak elő. Az értékek típusát az adott operátor és operandusok ismeretében meg lehet határozni.
A kifejezésnek ennek megfelelően mindig levezethető a típusa. Ezt a típust a kifejezés típusának nevezzük.
A szabály szerint egy értékadó utasítás RHS típusának vagy egyformának kell lennie az LHS típusával, vagy léteznie kell implicit típuskonverziónak az RHS típus -> LHS típus irányában.
Értékadás érték típusú változók között
Az érték típusú változókhoz tartozó memóriaterületen (valahány bájtnyi terület) az adott változók értékei tárolódnak. Két ilyen változó közötti értékadás során ezen bájtok másolódnak át egyik területről a másikra. Az átmásolás után a két változó a továbbiakban nem áll kapcsolatban egymással.
Pl.:
double a =12.3; // az ’a’ memóriaterületének feltöltése
double b = a; // 12.3 átmásolása a ’b’ területére
a = 14.5; // az ’a’ memóriaterületének újbóli feltöltése
Console.WriteLine(b); // 12.3 íródik ki
b = b*2;
Console.WriteLine(a); // 14.5 íródik ki
Mivel a példában szereplő a és b változók külön memóriaterületen helyezkednek el, így az a-ra vonatkozó értékadó utasítás nem változtatja meg a b-hez tartozó területet, így a b változóban lévő értéket sem.
Értékadás referencia típusú változók között I.
A referencia típusú változók elsődlegesen egy memóriacímet tárolnak. A változó tényleges, típusának megfelelő értéke ezen a memóriacímen található. Ilyen típus a sztring típus is.
string s = ”almafa”;
… esetén a memóriában eltárolásra kerül valahol az ”almafa” szöveg (14 byte-on), majd az s változóba bekerül ezen memóriaterület címe.
string m = s;
Két referencia típusú változó közötti értékadás során nem a típushoz tartozó érték kerül lemásolásra (duplikálás), hanem csak a memóriacímek másolódnak le.
A fenti esetben az m változóba átmásolódik az s-ben tárolt memóriacím. Így e pillanattól kezdve az m változó is az ”almafa” szövegre mutat, az m változó értéke is az ”almafa” szöveg lesz.
Ennek az az előnye, hogy egy memóriacím 4 byte-os adat, melynek lemásolása nagyon gyorsan végrehajtható. Ugyanakkor egy sztring érték akár több ezer karakter is lehet, melynek lemásolása viszont lassú és időigényes, nem is beszélve a memóriapocsékolásról.
Értékadás referencia típusú változók között II.
A referencia típusú változók elsődlegesen egy memóriacímet tárolnak. A változó tényleges, típusának megfelelő értéke ezen a memóriacímen található. Ilyen típus a tömb típus is.
int[] v = new int[10];
… esetén a memóriában eltárolásra kerül valahol a 10 db int elem, a v, majd a v változóba bekerül ezen memóriaterület címe.
int[] k = v;
Két referencia típusú változó közötti értékadás során nem a típushoz tartozó érték kerül lemásolásra (duplikálás), hanem csak a memóriacímek másolódnak le.
A fenti esetben a k változóba átmásolódik a v-ben tárolt memóriacím. Így e pillanattól kezdve a k változó is a fenti 10 elemű vektor.
Ekkor azonban vigyázni kell, hiszen a
k[3] = 12;
során a k vektor 4. elemének értékét megváltoztatjuk, de mivel ugyanezen 10 elem tartozik a v vektorhoz is, úgy a …
Console.WriteLine( v[3] );
… már ezen 12 értéket fogja megjeleníteni!
Értékadás referencia típusú változók között III.
A referencia típusú változók elsődlegesen egy memóriacímet tárolnak. A változó tényleges, típusának megfelelő értéke ezen a memóriacímen található. Ilyen típus a class kulcsszóval képzett rekord típus is (tegyük fel, hogy a DVD egy ilyen class alapú rekord típus).
DVD a = new DVD();
… esetén a memóriában eltárolásra kerül valahol a DVD rekord típusban felsorolt mezők, majd az a változóba bekerül e memóriaterület címe.
DVD b = a;
Két referencia típusú változó közötti értékadás során nem a típushoz tartozó érték kerül lemásolásra (duplikálás), hanem csak a memóriacímek másolódnak le.
A fenti esetben a b változóba átmásolódik az a-ben tárolt memóriacím. Így e pillanattól kezdve a b változó is a fenti rekord-példányt jelöli.
Ekkor azonban vigyázni kell, hiszen a
b.Cime =”Alma”;
során a b vektor Cime mezőjének megváltoztatjuk az értékét. De mivel ugyanezen rekord-példány tartozik az a változóhoz is, úgy a …
Console.WriteLine( a.Cime );
… már ezen ”Alma” értéket fogja megjeleníteni!