Kirjoitetaan samanniminen funktio, mutta annetaan sille funktion määrittelyrivillä (esittelyrivillä, otsikkorivillä, eng. header row tai function signature) kolme parametria kahden sijaan. Toteutetaan funktio myös saman tien.
Mutta nyt huomaamme, että meillä on melkein sama koodi näissä kahdessa funktiossa. Muutetaan ensimmäistä funktiota siten, että kutsutaan ensimmäisestä funktiosta (joka osaa vähemmän) toista funktiota (joka osaa enemmän). Annetaan kolmanneksi summattavaksi luvuksi (siis kolmanneksi parametriksi) 0.
Tämän esimerkin avulla näimme yksinkertaisella tavalla sen, mitä kuormittaminen tarkoittaa. Seuraava esimerkki valottaa kuormittamisen hyötyjä paremmin.
6.5.2 Vakiokokoinen lumiukko vs ukon koko parametrina
Voimme luoda vakiokokoisen lumiukon seuraavalla aliohjelmalla.
/// <summary>
/// Aliohjelma piirtää vakiokokoisen lumiukon
/// annettuun paikkaan.
/// </summary>
/// <param name="peli">Peli, johon lumiukko tehdään.</param>
/// <param name="x">Lumiukon alimman pallon x-koordinaatti.</param>
/// <param name="y">Lumiukon alimman pallon y-koordinaatti.</param>
public static void PiirraLumiukko(Game peli, double x, double y)
{
PhysicsObject alapallo, keskipallo, ylapallo;
alapallo = new PhysicsObject(2 * 100.0, 2 * 100.0, Shape.Circle);
alapallo.X = x;
alapallo.Y = y;
peli.Add(alapallo);
keskipallo = new PhysicsObject(2 * 50.0, 2 * 50.0, Shape.Circle);
keskipallo.X = x;
keskipallo.Y = alapallo.Y + 100 + 50;
peli.Add(keskipallo);
ylapallo = new PhysicsObject(2 * 30.0, 2 * 30.0, Shape.Circle);
ylapallo.X = x;
ylapallo.Y = keskipallo.Y + 50 + 30;
peli.Add(ylapallo);
}
Voimme kutsua tätä aliohjelmaa Begin
:stä vaikkapa seuraavasti.
Mutta entäs jos haluaisimmekin piirtää tämän lisäksi joskus eri kokoisiakin ukkoja? Toisin sanoen voisi olla tarve, että PiirraLumiukko
tekisi meille "vakiokokoisen" ukkojen lisäksi myös halutessamme jonkun muun kokoisen ukkelin. Kutsut Begin
:ssä voisivat näyttää tältä.
Mutta nyt kääntäjä antaa esimerkiksi virheilmoituksen
No overload for method 'PiirraLumiukko' takes 4 arguments.
Joten kirjoitetaan uusi aliohjelma, jonka nimeksi tulee PiirraLumiukko
(kyllä, samanniminen), mutta peli
-parametrin ja paikan lisäksi parametrina annetaan myös alapallon säde.
Siirretään nyt koodi alkuperäisestä aliohjelmasta tähän uuteen, ja laitetaan pallojen säde riippumaan parametrina annetusta säteestä. Lisäksi laitetaan keski- ja yläpallon paikat riippumaan pallojen koosta! Uusi (neljäparametrinen) aliohjelma näyttäisi nyt seuraavalta.
public static void PiirraLumiukko(Game peli, double x, double y, double sade)
{
PhysicsObject alapallo, keskipallo, ylapallo;
alapallo = new PhysicsObject(2 * sade, 2 * sade, Shape.Circle);
alapallo.X = x;
alapallo.Y = y;
peli.Add(alapallo);
// keskipallon koko on 0.5 * sade
keskipallo = new PhysicsObject(2 * 0.5 * sade, 2 * 0.5 * sade, Shape.Circle);
keskipallo.X = x;
keskipallo.Y = alapallo.Y + alapallo.Height / 2 + keskipallo.Height / 2;
peli.Add(keskipallo);
// ylapallon koko on 0.3 * sade
ylapallo = new PhysicsObject(2 * 0.3 * sade, 2 * 0.3 * sade, Shape.Circle);
ylapallo.X = x;
ylapallo.Y = keskipallo.Y + keskipallo.Height / 2 + ylapallo.Height / 2;
peli.Add(ylapallo);
}
Nyt voimme kutsua kolmeparametrisesta PiirraLumiukko
-aliohjelmasta tuota "versiota", joka osaa tehdä asioita enemmän ilman, että copy-pastetamme koodia.

Onko pelisysteemin sisässä siis vakiokokoisen lumiukon mitat jo valmiina, joihin tuossa "aliohjelma piirtää vakiokokoisen lumiukon mitat annettuun paikkaan"- osuudessa aliohjelmakutsulla viitataan? Sillä vaan mietin kun tässä oppimaani sisäistäessä en saa kunnolla kosketusta siihen että minkä vuoksi parametreiksi riittää vain "peli, x, y, 100"- koordinaatit eikä sen kummempia tietoja..
VL: Siis kommenteissa sanotaan kuten asia on. Ko aliohjelma piirtää aina vakio 100-säteisen pallon alimmaksi palloksi. Siinä alempana on sitten se aliohjelma, jolle annetaan parametrina tuo 100 jotta se tuolla25 rivin kutsulla piirtää nimenomaan 100 (vakio) kokoisen ukon. "Pelisysteemin" sisällä ei ole mitään "ylimääräistä" lumiukkoon liittyvää. Ainostaan tuo PhysicsObject
-luomiseen tarvittava koneisto (jolla nyt siis tehdään niitä palloja).
Jaa niin siis aliohjelmalle pitää aina kuitenkin ilmoittaa neljäntenä parametrinä sädemitta joka alimmalla pallolla halutaan olevan, että "vakiokoko"- sanan "kirjoittaminen" ei varsinaisesti auta vielä mitään?
VL: Siinähän on kaksi eri aliohjelmaa. Toinen piirtää aina 100-säteisellä alapalolla ja toinen tarvitsee sen säteen. Ks rivit 25 ja 26. Se että tuo 100-säteisen piirtävä kutsuu sitä toista, niin säästytään ettei tarvitse koko koodia kopioida uudestaan.
Kysymykseni tais olla vahingossa vähän epäselvä, mietintöni koski siis tuota ns alempaa aliohjelmaa ja tarkennusta siihen, eli (peli, x, y, 100)- parametreihin. Ja siis nuo x ja y- parametrit ilmeisesti vain viittaavat noihin ylempänä kahdessa aliohjelmassa oleviin koordinaattiparametreihin. Mietin vielä että jos tuo ylempi aliohjelma piirtää siis 100-säteisen alapallon tuon alemman aliohjelmaparametrin perusteella, niin se että tuohon ylempään toiseen aliohjelmaan kirjoittaa säteen (50.0) jo valmiiksi, ajaa tavallaan yli tuon allaolevan 100-sädekäskyn, eli että ohjelma ei tavallaan kuitenkaan mene sekaisin siitä että tarvitseeko sen piirtää toiseen koordinaattiin 100 vai 50- säteinen pallo alapalloksi? Jos siis haluttaisiin että molempiin eri kohtiin tulevat lumiukot olisivat keskenään samankokoisia niin silloin jätettäisiin kirjoittamatta tuo 50- säde? Hetkinen.. "Se että tuo 100-säteisen piirtävä kutsuu sitä toista".. mitä toista? Ihan siis tuota alinta aliohjelmarimpsua? Eli siis että kun PiirraLumiukko(this, -200, Level.Bottom + 300.0); - niminen ohjelma kutsuu PiirraLumiukko(peli, x, y, 100); -nimistä ohjelmaa, niin se sitä kautta kutsuu siis tuota alinta eli public static void PiirraLumiukko(Game peli, double x, double y, double sade) -nimistä ohjelmaa?
VL: Nyt hieman varoivaisuutta termien kanssa. Ohjelmassa on kolem aliohjelmakutsua (laita HighLight päälle) riveillä: 25, 26 ja 41. Ohjelmassa on kaksi aliohjelmaa (ja Begin metodi) alkaen riveiltä: 39 ja 52. Kun ohjelma lähtee käyntiin, on suoritusjärjetys rivit: 24,25,39,41,52,54-69,42,26,52,54-69,28,29,30. Kannattaa kokeilla tuota debuggereissa. Myäs sanaa "viitata" kannattaa varoa, koska se on varattu viitemuuttujien käyttöön.
Ok, no nyt sain kuitenkin hahmotettua ensalkuun paremmin että mikä ohjelman osa tekee mitäkin (katson kyllä nuo termistötkin paremmin läpi vielä kun tarttis saada ne paremmin haltuun muutenkin, aamuyön virkeyksissä tuli vaan mietittyä että kuinka saa kysymysajatukset selkeimmin ilmi. Ja toisaalta, tällasen "oikean" esimerkin kautta osoitettuna ja havainnollistettuna ne parhaiten myös oppii).
—.
7. Muuttujat
muuttujanTyyppi muuttujanNimi = muuttujanArvo;
muuttujanNimi = muuttujanUusiArvo;
Esim:
int maailmanTarkoitus = -42;
maailmanTarkoitus = -1 * maailmanTarkoitus;
Muuttujat (variable) toimivat ohjelmassa tietovarastoina erilaisille asioille. Muuttuja on kuin pieni laatikko, johon voidaan varastoida asioita, esimerkiksi lukuja, sanoja, tietoa ohjelman käyttäjästä ja paljon muuta. Proseduaalisissa kielissä ilman muuttujia järkevä tiedon käsittely olisi oikeastaan mahdotonta. Funktio-ohjelmoinnissa tosin asiat ovat hieman toisin. Olemme jo ohimennen käyttäneetkin muuttujia, esimerkiksi Lumiukko-esimerkissä teimme PhysicsObject
-tyyppisiä muuttujia p1
, p2
ja p3
. Vastaavasti PiirraLumiukko
-aliohjelman parametrit (Game peli, double x, double y)
ovat myös muuttujia: Game
-tyyppinen oliomuuttuja peli
, sekä double-alkeistietotyyppiset muuttujat x
ja y
.
Termi muuttuja on lainattu ohjelmointiin matematiikasta, mutta niitä ei tule kuitenkaan sekoittaa keskenään - muuttuja matematiikassa ja muuttuja ohjelmoinnissa tarkoittaa hieman eri asioita. Tulet huomaamaan tämän seuraavien kappaleiden aikana.
Muuttuja arvo muuttuu vain sijoituslauseen suoritushetkellä:
int ika = 21;
int nyt = 2021;
int syntymavuosi = nyt - ika; // arvoksi tulee 2000
nyt = 2022; // syntymävuosi on edelleen 2000
Muuttujan arvo ei muutu vaikka sen arvon tuottavissa lausekkeissa jokin myöhemmin muuttuisi. Esimerkiksi edellä syntymavuosi
on edelleen 2000
vaikka jatkossa tehtäisiin sijoitus.
Eli lausekkeen arvo lasketaan sillä hetkellä kun sijoitus tehdään.
Muuttujien arvot tallennetaan keskusmuistiin tai rekistereihin, mutta ohjelmointikielissä voimme antaa kullekin muuttujalle nimen (identifier), jotta muuttujan arvon käsittely olisi helpompaa. Muuttujan nimi onkin ohjelmointikielten helpotus, sillä näin ohjelmoijan ei tarvitse tietää tarvitsemansa tiedon keskusmuisti- tai rekisteriosoitetta, vaan riittää muistaa itse nimeämänsä muuttujan nimi. [VES]
Koska kääntäjän pitää osata varata muuttujalle oikean kokoinen muistialue, pitää muuttujalle esitellä myös tyyppi. Muuttujan tyyppiä tarvitaan myös siksi, että tiedetään miten muistipaikkaan tallennettua tietoa pitää käsitellä. Jotta ymmärtäisimme erilaisien tietotyyppien erilaisia tallennustapoja, tutustumme myöhemmin muun muassa binäärilukuihin. Esimerkiksi kahdeksan bitin yhdistelmä, eli tavu 01000001
voidaan tulkita esimerkiksi kirjaimeksi A tai etumerkittömäksi kokonaisluvuksi 65.
Esimerkiksi lauseessa Console.WriteLine(a)
ei voitaisi tietää mitä pitää tulostaa, mikäli ei tiedetä muuttujan a
tyyppiä. Aivan vastaavasti kuin lauseesta kuusi palaa
, ei voida tietää mitä sillä tarkoitetaan jos asiayhteys ei ole selvillä.
7.1 Muuttujan määrittely
Kun matemaatikko sanoo, että "n on yhtä suuri kuin 1", tarkoittaa se, että tuo termi (eli muuttuja) n
on jollain käsittämättömällä tavalla sama kuin luku 1. Matematiikassa muuttujia voidaan esitellä tällä tavalla "häthätää".
Ohjelmoijan on kuitenkin tehtävä vastaava asia hieman tarkemmin. C#-kielessä tämä tapahtuisi kirjoittamalla seuraavasti:
Ensimmäinen rivi tarkoittaa väljästi sanottuna, että "lohkaise pieni pala - johon mahtuu int
-kokoinen arvo - säilytystilaa tietokoneen muistista, ja käytä siitä jatkossa nimeä n
". Toisella rivillä julistetaan, että "talleta arvo 1 muuttujaan, jonka nimi on n
, siten korvaten sen, mitä kyseisessä säilytystilassa mahdollisesti jo on".
Merkki =
on sijoitusoperaattori ja siitä puhutaan enemmän myöhemmässä luvussa.
Mikä sitten on tuo edellisen esimerkin int
?
C#:ssa jokaisella muuttujalla täytyy olla tietotyyppi (usein myös lyhyesti tyyppi). Tietotyyppi on määriteltävä, jotta ohjelma tietäisi, millaista tietoa muuttujaan tullaan tallentamaan. Toisaalta tietotyyppi on määriteltävä siksi, että ohjelma osaa varata muistista sopivan kokoisen lohkareen muuttujan sisältämää tietoa varten. Esimerkiksi int
-tyypin tapauksessa tilantarve olisi 32 bittiä (4 tavua), byte
-tyypin tapauksessa 8 bittiä (1 tavu) ja double
-tyypin 64 bittiä (8 tavua). Muuttuja määritellään (declare) kirjoittamalla ensiksi tietotyyppi ja sen perään muuttujan nimi. Muuttujan nimet aloitetaan C#:ssa pienellä kirjaimella, jonka jälkeen jokainen uusi sana alkaa aina isolla kirjaimella. Kuten aiemmin mainittiin, tämä nimeämistapa on nimeltään camelCasing.
Tuo mainitsemamme int
on siis tietotyyppi, ja int
-tyyppiseen muuttujaan voi tallentaa kokonaislukuja. Muuttujaan n
voimme laittaa lukuja 1, 2, 3, samoin 0, -1, -2, ja niin edelleen, mutta emme lukua 0.1 tai sanaa "Moi". Mutta mitä ikinä laitammekin, niin muuttujassa voi olla vain yksi arvo kerrallaan. Kun muuttujaan sijoitetaan uusi arvo, ei edelliseen arvoon pääse enää mitenkään käsiksi.
Henkilön iän voisimme tallentaa seuraavaan muuttujaan:
Huomaa, että tässä emme aseta muuttujalle mitään arvoa, vain määrittelemme muuttujan int
-tyyppiseksi ja annamme sille nimen.
Samantyyppisiä muuttujia voidaan määritellä kerralla useampia erottamalla muuttujien nimet pilkulla. Tietotyyppiä double käytetään, kun halutaan tallentaa desimaalilukuja.
Määrittely onnistuu toki myös erikseen (joka on jopa suositeltavampi tapa):
Miksi tietotyypin määrittely erikseen on jopa suositeltavampi tapa kuin samalla rivillä? Siksikö, että ne ovat paljaalla silmällä helpompi löytää koodista vai jokin muu syy?
—VL: kyllä tuossa selkeämmin näkyy mitä muuttujia on esitelty. Ja on helpompi vaihtaa yhden muuttujan typpiä vahingossa vaihtamatta toista. Lisäksi C:ssä
int* a, b; // luo osoittinmuuttujan
// ja yhden intin
int *c; // kun alla oleva taas
int d; // selkeämmin näyttää eron
— Muuttujaan voi asettaa arvon myös jo määrittelyn yhteydessä. Tällöin puhutaan arvon alustamisesta. Huomattakoon että arvo voi tulla myös lausekkeen tuloksena.
muuttujanTietotyyppi muuttujanNimi = VAKIO;
muuttujanTietotyyppi muuttujanNimi = lausekeJokaTuottaaArvon;
Miksi tässä ei tarvita $-merkkiä Writelinen sulkujen sisään, kuten edellisen kappaleen esimerkeissä?
VL: Tuo $ tekee merkkijonosta erilaisen muotoilijan, missä muuttujien arvot saa kirjoittaa suoraan lainausmerkkehin. Ks lisää luvusta 12.7.
—Muuttujalle sijoitettavan arvon (tai lausekkeen arvon) tulee olla tyypiltään sellainen, että se voidaan sijoittaa muuttujaan. Yksinkertaisiin lainausmerkkeihin kirjoitettu kirjain on arvo, joka voidaan sijoittaa char
-tyyppiseen muuttujaan. Esimerkiksi int-tyyppiseen muuttujaan ei voi sijoittaa reaalilukua:
mutta reaalilukuun voi sijoittaa kokonaisluvun
Huomattakoon, että reaalilukujen (mm. double
) desimaalierottimen ohjelmakoodissa on aina piste (.
) eikä tuhaterottimia käytetä.
Mitkä seurvaavista muuttujien määrittelyistä ovat sallittuja:
Miksi muuttujalle ei voi antaa nimeksi numeroa? Esim. tässä tapauksessa tuo int 4;
VL: Mietis mitä tästä seuraisi:
int 4 = 3;
Console.WriteLine(4);
Ja jotta tuota olisi helpompi estää, ei muuttujan nimi edes saa alkaa numerolla (vaikka se olisi periaatteessa vielä tehtävissä).
—7.2 Alkeistietotyypit
C#:n tietotyypit voidaan jakaa alkeistietotyyppeihin (primitive types, perustyyppi, perustietotyyppi) ja oliotietotyyppeihin (reference types). Oliotietotyyppeihin kuuluu muun muassa käyttämämme PhysicsObject
-tyyppi, jota pallot p1
jne. olivat, sekä merkkijonojen tallennukseen tarkoitettu string
-olio. Oliotyyppejä käsitellään myöhemmin luvussa 8.
Eri tietotyypit vaativat eri määrän kapasiteettia tietokoneen muistista. Vaikka nykyajan koneissa on paljon muistia, on hyvin tärkeää valita oikean tyyppinen muuttuja kuhunkin tilanteeseen. Suurissa ohjelmissa ongelma korostuu hyvin nopeasti käytettäessä muuttujia, jotka kuluttavat tilanteeseen nähden kohtuuttoman paljon muistikapasiteettia. C#:n alkeistietotyypit on lueteltu alla.
Taulukko 1: C#:n alkeistietotyypit koon mukaan järjestettynä.
Tällä kurssilla tärkeimmät alkeistietotyypit ovat: bool
, char
, int
ja double
. Huomaa että vaikka bool
on informaatiosisältönä 1 bittiä, vie se muistia kuitenkin yhden tavun, eli 8 bittiä.
Tässä monisteessa suositellaan, että desimaalilukujen talletukseen käytetään aina double
-tietotyyppiä (jossain tapauksissa jopa decimal
-tyyppiä), vaikka monessa muussa lähteessä float
-tietotyyppiä käytetäänkin. Tämä johtuu siitä, että liukuluvut, joina desimaaliluvut tietokoneessa käsitellään, ovat harvoin tarkkoja arvoja tietokoneessa. Itse asiassa ne ovat tarkkoja vain kun ne esittävät jotakin kahden potenssin yhdistelmiä, kuten esimerkiksi 2.0, 7.0, 0.5 tai 0.375.
Useimmiten liukuluvut ovat pelkkiä approksimaatioita oikeasta reaaliluvusta. Esimerkiksi lukua 0.1 ei pystytä tietokoneessa esittämään biteillä tarkasti perustietotyypeillä. Tällöin laskujen määrän kasvaessa lukujen epätarkkuus vain lisääntyy. Tämän takia onkin turvallisempaa käyttää aina double
-tietotyyppiä, koska se suuremman bittimääränsä takia pystyy tallettamaan enemmän merkitseviä desimaaleja.
Tietyissä sovelluksissa, joissa mahdollisimman suuri tarkkuus on välttämätön (kuten pankki- tai nanotason fysiikkasovellukset), on suositeltavaa käyttää korkeimpaa mahdollista tarkkuutta tarjoavaa decimal
-tyyppiä. Reaalilukujen esityksestä tietokoneessa puhutaan lisää kohdassa 26.6. [VES][KOS]
Seuraavassa esimerkki mitä tapahtuu, kun lasketaan yhteen kaksi liian isoa kokonaislukua tai muuten lisätään muuttujaa liikaa.
Mitä esim. b++ tarkoittaa? Yritin etsiä sitä monisteesta, mutta nämä tässä olevat maininnat b++:sta ovat ainoat.
VL: Kokeileppa etsiä pelkkää ++
. Muuttujilla voi olla eri nimiä ja jos jossakin on kerrottu mitä on a++
, niin ei erikseen tarvitse sanoa mitä on b++
.
Edeltävän taulukon mukaan luku2 pitäisi riittää olla tyyppi int (2,000,000,000 < 2,147,483,647), mutta jos molemmat sekä luku1 että luku2 jättää tyypiksi int, niin double summa = luku1 + luku2 tuottaa virheellisen tuloksen. Sen sijaan int luku1 + double luku2 toimii. Mitä en nyt tajua?? Anteeksi sekava selitys
VL: Kumpikin alkuperäinen int-tyyppinen muuttujat ovat arvoalueessa. Mutta niiden summa ei enää ole. Jos summan tyypin vaihtaa double, niin se ei yksin riitä, koska lasku tehdään "suurimmalla" tyypillä mitä laskussa on, eli int+int on edelleen int. Jos toisen muuttujan tyyppi vaihdetaan double-tyyppiseksi, niin silloin laskut suoritetaan double-tyyppisenä. Sekin auttaisi jos olisi
double summa = 1.0*luku1 + luku2; // nyt on double + int
— 7.3 Arvon asettaminen muuttujaan
Muuttujaan asetetaan arvo sijoitusoperaattorilla (assignment operator) =
. Lauseita, joilla asetetaan muuttujille arvoja, sanotaan sijoituslauseiksi (assignment statement). On tärkeää huomata, että sijoitus tapahtuu aina oikealta vasemmalle: sijoitettava on yhtäsuuruusmerkin oikealla puolella ja kohde merkin vasemmalla puolella.
Miksi float ei toimi?
VL: Jos on float
-tyyppinen muuttuja vaikka x
, niin sille pitäisi sijoittaa float
vakio:
Saako tässä asettaa sellaisen formaatin, että desimaalit näkyisivät myös x:lle?
System.Console.WriteLine("x = {0:0.00}", x);
jos paino ja pituus desimaaleisa ei int toimi mutta double toimii, niin miksi tämäohjelma ei ote vastaan doubletietotyyppiä? kai int ja double pitäis pystyä laittamaan samaan koodiin/ohjelmaan niinkun pystyy int ja sbyte teht 7.1.?
VL: tyyppejä ei voi sotkea. Oletko antanut muuttajille tyypit? Jos muuttujan tyyppi on int
, ei siihen voi sijoittaa reaalilukua (double
). Mutta toisinpäin onnistuu, eli double
muuttujalle voi sijoittaa kokonaislukuarvon (koska se on myös reaaliluku samalla).
Huomaa että reaalilukuvakioissa käytetään desimaalipistettä, ei pilkkua.
Muuttuja täytyy olla määritelty tietyn tyyppiseksi ennen kuin siihen voi asettaa arvoa. Muuttujaan voi asettaa vain määrittelyssä annetun tietotyypin mukaisia arvoja tai sen kanssa sijoitusyhteensopivia arvoja. Esimerkiksi liukulukutyyppeihin (float ja double) voi sijoittaa myös kokonaislukutyyppisiä arvoja, sillä kokonaisluvut ovat reaalilukujen osajoukko. Alla sijoitamme arvon 4 muuttujaan nimeltä luku2, ja kolmannella rivillä luku2-muuttujan sisältämän arvon (4) muuttujaan, jonka nimi on luku1.
Toisinpäin tämä ei onnistu: double-tyyppistä arvoa ei voi sijoittaa int-tyyppiseen muuttujaan. Alla oleva koodi ei kääntyisi:
Jos edellä oleva sijoitus int <- double
halutaan välttämättä tehdä, niin silloin on käytettävä tyypin muunnosta eli typecastia (kokeile edelliseen, vaihda myös 4.0
tilalle 4.8
). Tosin tyypinmuunnokseen turvautuminen on aina huono ratkaisu.
Kun decimal
-tyyppinen muuttuja alustetaan jollain luvulla, tulee luvun perään (ennen puolipistettä) laittaa m
(tai M
)-merkki. Samoin float
-tyyppisten muuttujien alustuksessa perään laitetaan f
(tai F
)-merkki ja long
-tyyppisten perään L
.
Mitä tarkoitetaan alustuksella?
VL: muuttujan voi joko vaan esitellä tai sen voi esitellä ja alustaa sille samalla alkuarvon. Voisi sen sanoa niinkin, että annetaan muuttujalla alkuarvo samalla kun sen tila varataan.
—Huomaa, että char-tyyppiseen muuttujaan sijoitetaan arvo laittamalla merkki yksinkertaisten heittomerkkien väliin, esimerkiksi näin.
Näin sen erottaa myöhemmin käsiteltävästä string
-tyyppiseen muuttujaan sijoittamisesta, jossa sijoitettava merkkijono laitetaan (kaksinkertaisten) lainausmerkkien väliin, esimerkiksi seuraavasti.
Sijoituslause voi sisältää myös monimutkaisiakin lausekkeita, esimerkiksi aritmeettisia operaatioita:
Sijoituslause voi sisältää myös muuttujia.
Mistä C# kaivaa tuohon 5.4 * 5.4 laskutoimitukseen tuon nelosen loppuun? (Ala = 29.16000..004) Johtuuko jotenkin 2:n potensseista? Ja mitenkä tällaisen pystyy väistämään? On tullut itsellä vastaan mm. eräässä taloushallinnon järjestelmässä ja olisi voinut olla pahakin virhe jos olisi mennyt itseltä ohi...
VL: 5.4 ei ole tarkka luku ja kun sillä lähdetään operoimaan tulos ei tarkkene. Vähän sama kuin 0.333333... on 10-järjestelmän laskuissa katkaistava jostakin. Virhe ei johdu kielestä yksin vaan prosessorin tavasta laskea. Tulostuksessa voisi rajata desimaaleja.
—Eli sijoitettava voi olla mikä tahansa lauseke, joka tuottaa muuttujalle kelpaavan arvon. Yhdistämällä muuttujia ja operaatoita voi lauseke olla edellisiäkin "monimutkaisempi":
Huomaa edellä, että vaikka paperilla kaavoja kirjoitettaessa ei tarvita kertomerkkiä, niin ohjelmointikielissä käytetään *
-merkkiä kertomerkkinä.
C#:ssa täytyy aina asettaa joku arvo muuttujaan ennen sen käyttämistä. Kääntäjä ei käännä koodia, jossa käytetään muuttujaa jolle ei ole asetettu arvoa. Alla oleva ohjelma ei siis kääntyisi.
Virheilmoitus näyttää tältä:
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.