C vs C#

Site: vpf.gnomio.com
Course: 19/20: Programiranje IT 3
Book: C vs C#
Printed by: Guest user
Date: Saturday, 20 December 2025, 11:40 AM

Description

C# je programski jezik koji nam omogućuje pisanje kako konzolnih tako i Windows aplikacija, pa čak i aplikacija za Web. U prvom delu koji se odnosi na osnove programskog jezika C# primeri će se odnositi na delove koda neke konzolne aplikacije dok će se u drugom delu detaljnije objašnjavati razvoj Windows aplikacija te će i primeri biti sa odgovarajućim grafičkim korisničkim interfejsom.

Svaki programski jezik ima elemente koji ga karakterišu i to su:

  • azbuka,
  • rezervisane reči,
  • konstante,
  • promenljive.
Azbuku programskog jezika C# čine mala i velika slova engleskog alfabeta, cifre, specijalni znaci (npr. za aritmetičke operacije, relacije, itd.) i razdelnici (tačka, dvotačka, tačka zarez, itd.). - isto kao u C.

1. Promenljive

Programski jezik C# spada u grupu tipiziranih jezika. Svaka promenljiva mora da se deklariše pre upotrebe. Deklaracijom promenljive definiše se:

  • naziv,

  • tip,

  • njena početna vrednost (opciono) i

  • vidljivost tj. prava pristupa u slučaju da je promenljiva članica klase

Sintaksa:

vidljivost tip naziv = početna vrednost;

Primer:

public string Ime;
private int BrojUcenika = 1;
int x, y;
double alfa, Plata, UDALJENOST;

Programski jezik C# je case sensitive jezik, što znači da pravi razliku između malih i velikih slova. Svaka linija u kodu se završava simbolom ;. Prvi znak imena promenljive ne može da bude cifra. Svi specijalni znaci osim znaka _ ne mogu biti deo imena promenljive.


1.1. var

 – implicitno zadavanje tipa lokalnih promenljivih -

Često se dešava da deklarišete i inicijalizujete promenljivu u jednom koraku. Ako je kompajler u stanju da na osnovu inicijalizacionog izraza zaključi o kom se tipu radi, možete koristiti reč var umesto deklaracije tipa. Na primer:

var x = “hello”;

var z = (float)Math.PI;
Ovo je potpuno ekvivalentno sledećem:

string x = “hello”;

float z = (float)Math.PI;

1.2. Konstante

Konstanta je promenljiva čija se vrednost ne može menjati. Konstanta se dobija stavljanjem ključne reči const ispred promenljive prilikom njene deklaracije i inicijalizacije.

const int broj1 = 100;
Konstante moraju biti inicijalizovane prilikom deklaracije, i kada im se jednom dodeli vrednost, ona se ne može promeniti. Takođe, konstanta se ne može inicijalizovati vrednošću neke promenljive, odnosno vrednost kojom se inicijalizuje konstanta mora biti dostupna u vreme kompajliranja.

2. Tipovi podataka u C#

Dele se u 2 grupe:

  • VREDNOSNI TIPOVI

  • REFERENTNI TIPOVI

Promenljive vrednosnog tipa u okviru svog memorijskog prostora čuvaju vrednost te promenljive, dok  promenljive referentnog tipa čuvaju adresu (referencu) memorijskog prostora na koji pokazuju.

VREDNOSNI tipovi:

  • numerički (int, uint, long, ulong, double, float…)
  • znakovni char
  • logički bool, Boolean
  • enumeracije enum
  • strukture struct

REFERENTNI tipovi:

  • stringovi
  • nizovi (svih vrsta)
  • klase

Između nekih tipova su moguće konverzije. Konverzija podataka mogu biti IMPLICITNE i EKSPLICITNE. Implicitne su automatske i kod njih nije potrebno navoditi dodatne komande. Eksplicitna konverzija se vrši ili kastovanjem (cast – u zagradi ispred promenljive ili izraza navedemo tip npr (double)x) ili konverzionim metodama.

Svi tipovi u c# se mogu konvertovati u string.

Sve аplikаcije mаnipulišu podаcimа nа neki nаčin. Prilikom te mаnipulаcije, podаci se privremeno (ili trajno) smeštаju u promenljive (vаrijаble), (koje se pre korišćenjа morаju definisаti).

Definisаnjem promenljivih rezerviše se prostor u memoriji nа osnovu:
a) imenа promenljive,
b) tipа podаtаkа kome dаtа promenljivа pripаdа.

Tip podаtаkа neke promenljive određuje:
a) dozvoljene vrednosti zа promenljivu,
b) operаcije koje se mogu vršiti nаd njom,
c) memorijski prostor koji se definiše za tu promenljivu.

Već smo rekli da u C# postoje dve vrste tipovа podаtаkа: VREDNOSNI I REFERENTNI

Promenljive vrednosnog tipа direktno sаdrže podаtke i čuvаju se u delu operаtivne memorije koji se nаzivа STACK.

Ne može se desiti dа izvršаvаnje operаcijа nаd jednom promenljivom utiče nа drugu promenljivu (jer promenljive sаdrže svoju kopiju podаtаkа).

Vrednosni tipovi podаtаkа se dele nа:
A - proste (predefinisаne) vrednosne tipove podаtаkа
B - korisnički-definisаne vrednosne tipove podаtаkа.

Prosti tipovi podаtаkа su ugrаđeni tipovi podаtаkа. Tu spаdаju:
1. celobrojni tipovi,
2. tipovi sа pokretnim zаrezom,
3. decimаlni tip,
4. logički tip i
5. znаkovni tip.

- zа nаznаčаvаnje dа neki broj predstаvljа tip decimal, a ne tip double, float, ili celobrojni tip, vrednosti se pridružuje znаk M.

- dа bi se vrednost logičkog tipа logickiTip moglа prikаzаti nа izlаzu, potrebno je da se logički tip podаtаkа konvertuje u tip string pomoću metode ToStringegg.

- Formаtirаnje izlаzа se ne odnosi sаmo nа tip decimal, već i nа ostаle tipove sа pokretnim zаrezom. Tаko će se broju sа pokretnim zаrezom pridružiti F, ukoliko se broj želi predstаviti kаo tip float, odnosno D, ukoliko se želi nаznаčiti dа se rаdi o tipu double.

Slično imаmo i kod predefinisаnih celobrojnih tipovа. Ukoliko jednu celobrojnu promenljivu želimo dа predstаvimo, npr. kаo long, njegovoj vrednosti ćemo pridružiti L .

- nаredbа Console.WriteLine može dа sаdrži promenljiv broj аrgumenаtа; prvi аrgument je string, koji može dа sаdrži numerisаne placeholdere , npr. {0}, {1} itd. (na mestu placeholdera će biti prikazana vrednost promenljive). 

- Zа svаki prost tip podаtаkа postoji rezervisаnа reč kojа predstаvljа pseudonim zа tipove koji su definisаni u .NET okruženju.

- Komentari se u C# pišu sa //

2.1. Numerički tipovi podataka

U brojčane (numeričke) tipove podataka spadaju celobrojni i decimalni tip (realni tip).

Za celobrojni tip se koriste sledeći identifikatori sbyte, byte, short, ushort, int, uint, long i ulong. Razlika između ovih tipova je u veličini broja koji mogu da prihvate kao promenljivu. Identifikatori sbyte, byte, short i ushort se koriste za manje cele brojeve (do 255), dok se za veće cele brojeve koriste int i uint. Identifikatori long u ulong koriste se za veoma velike cele brojeve.

Za realni tip koristimo: float, double i decimal. Razlika između ovih tipova je u obuhvatu i preciznosti.

Numeričke vrednosti se mogu koristiti za izvođenje matematičkih operacija (+ ,-, *, /).
Operator ‘%’ prikazuje ostatak posle celobrojnog deljenja.
Numeričke vrednosti možemo porediti pomoću logičkih operatora (==, <, <=, >, >=, !=).
Takođe, nad numeričkim operatorima se mogu izvršavati funkcije (Abs(x), Math.Exp(x), Math. Pow(x,y), Math.Sin(x)) itd.

A sad malo detaljnije:

Numeričkim tipovima podataka se predstavljaju celi i realni brojevi. Za predstavljanje celih brojeva postoji više tipova koji su prikazani u tabeli.

Tip

Opseg vrednosti

 Zauzeće memorije 

u bajtovima

.NET
tip

Sufiks

 sbyte

 -128 do 127

1

SByte


 byte

 0 do 255

1

Byte


 short

 -32 768 do 32 767

2

Int16


 ushort

 0 do 65 535

2

UInt16


 int

 -2 147 483 648 do 2 147 483 647

4

Int32


 uint

 0 do 4 294 967 295

4

UInt32

U

 long

 -9 223 372 036 854 775 808 do 9 223 372 036 854 775 807

8

Int64

L

 ulong

 0 do 18 446 744 073 709 551 615

8

UInt64

UL

U tabeli postoje tipovi koji počinju slovom "u" (unsigned) što znači da opseg vrednosti čine samo pozitivni celi brojevi.
Unapred definisani tipovi u jeziku C# alijasi su Framework tipova u imenskom prostoru System. Sledeće dve naredbe razlikuju se samo sintaksički:

int i = 5;
System.Int32 i = 5;
Realni brojevi su predstavljeni tipovima: float, double i decimal. Ovi tipovi se razlikuju po opsegu vrednosti i broju značajnih cifara. Među tipovima realnih brojeva, float i double se zovu tipovi s pokretnim zarezom (engl. floating-point types) i obično se koriste za naučna izračunavanja. Tip decimal se najčešće upotrebljava za finansijske proračune, gde su potrebni aritmetika brojeva sa osnovom 10 i velika preciznost. (Tehnički, decimal je takođe tip s pokretnim zarezom, mada se retko tako naziva.)

Tip

Opseg vrednosti

 Preciznost u broju 

cifara

 Zauzeće memorije u 

broju bajtova

.NET
tip

Sufiks

 float

 ± 1.5 x 10-45 do ± 3.4 x 1038

7

4

Single

F

 double

 ± 5 x 10-324 do ± 1.7 x 10308

15-16

8

Double

D

 decimal

 ± 1 x 10-28 do ± 7.9 x 1028

28-29

16

Decimal

M


Konverzije
C# može da konvertuje instance kompatibilnih tipova jedne u druge. Konverzijom uvek nastaje nova vrednost od postojeće. Konverzije mogu biti implicitne ili eksplicitne: implicitne konverzije se obavljaju automatski, dok je za eksplicitne konverzije potrebno pretvaranje (engl. cast). U sledećem primeru, implicitno konvertujemo tip int u tip long (koji ima dvaput veći kapacitet u bitovima od int) i eksplicitno konvertujemo tip int u tip short (koji ima upola manji kapacitet u bitovima od int):

int q = 555; // int je 32-bitni ceo broj
long w = q; /* Implicitna konverzija u 64-bitni ceo broj */
short r = (short)q; /* Eksplicitna konverzija u 16-bitni (kastovanje) ceo broj */
U opštem slučaju, implicitne konverzije su dozvoljene kada kompajler može da garantuje da će one uvek uspeti bez gubljenja informacija.
U suprotnom, morate obaviti eksplicitnu konverziju između kompatibilnih tipova.

Numerički sufiksi
Numerički sufiksi eksplicitno definišu tip konstante:

decimal d = 3.5M; // M = decimal (svejedno da li je malo ili veliko slovo)
Sufiksi U i L su retko kada potrebni, pošto se tipovi uint, long i ulong gotovo uvek mogu ili pogoditi ili implicitno konvertovati iz int.

Sufiksi F i M su najkorisniji i obavezni su pri navođenju frakcionih literala tipa float ili decimal. Bez sufiksa, sledeći iskaz se ne bi preveo, jer bi se smatralo da je vrednost 4.5 tipa double, koja se ne konvertuje implicitno u float ili decimal:

float f = 4.5F; // Neće se prevesti bez sufiksa
decimal d = -1.23M; // Neće se prevesti bez sufiksa
*
***

Deljenje celih brojeva
U operacijama deljenja celih brojeva uvek se odsecaju ostaci deljenja (brojevi se zaokružuju ka nuli). Deljenje promenljivom čija je vrednost nula izaziva grešku pri izvršavanju, engl. runtime error (DivideByZeroException).
Deljenje literalom ili konstantom 0 izaziva grešku pri prevođenju, engl. compile-time error.

Specijalne vrednosti tipova float i double

Za razliku od celobrojnih tipova, tipovi s pokretnim zarezom imaju vrednosti koje se u određenim operacijama tretiraju na poseban način. Te specijalne vrednosti su NaN (Not a Number – nije broj), +∞, –∞ i –0.
Klase float i double imaju konstante za NaN, +∞ i –∞ (kao i za druge vrednosti, uključujući MaxValue, MinValue i Epsilon). Na primer:

Console.Write (double.NegativeInfinity); // Minus beskonačno
Deljenjem broja različitog od nule nulom, dobija se beskonačna vrednost:

Console.WriteLine ( 1.0 / 0.0); // Beskonačno
Console.WriteLine (–1.0 / 0.0); // Minus beskonačno
Console.WriteLine ( 1.0 / –0.0); // Minus beskonačno
Console.WriteLine (–1.0 / –0.0); // Beskonačno
Deljenjem nule nulom ili oduzimanjem jedne beskonačne vrednosti od druge, dobija se NaN:

Console.Write ( 0.0 / 0.0); // NaN
Console.Write ((1.0 / 0.0) – (1.0 / 0.0)); // NaN


2.2. Znakovni tip podataka

Znakovni tip je char. Dozvoljene vrednosti su UNICODE znak, svaki znak se kodira sa dva bajta. Konstante tipa char se pišu navođenjem znaka između apostrofa.

Char konstanta predstavlja jedan znak pod apostrofima. Ne postoji implicitna konverzija, ali se u numerički tip može konvertovati kastovanjem:

char znak=’A’, slovo; 
i=(int)znak;    /*  celobrojna prom. i dobija ASCII vrednost znaka */

slovo=(char)((int)znak+1);   /* uvećava se vrednost konvertovanog znaka za 1, pa se opet  konvertuje u char. Kast je najvišeg prioriteta, te obratite pažnju na zagrade */

for(i=(int)’a’; i<=(int)’z’; i++) slovo=(char)i;      /* slovo redom  dobija vrednosti od ’a’  do ’z’ */

2.3. Logički tip podataka

Logički tip je bool (alijas tipa System.Boolean) i ima smo dve vrednosti: true i false. Koristi se jedan bajt za memorisanje podataka ovog tipa.

Boolean ili bool poseduje 2 konstante – true i false. Ne postoji implicitna konverzija sa ostalim tipovima. Konverzionom metodom se može prevesti u numerik: true u 1, a false u 0.

Boolean p,q; 

p=i<(int)slovo && i>a || i==(int)znak;


p=!p;


if( p ) q=false;


while (true){…}
/* beskonačan ciklus */

Promenljiva logičkog tipa može dobiti vrednost logičke konstante, logičke promenljive ili izraza. Logički izrazi se grade pomoću relacija >, <, <=, >=, ==, !=. Operandi u relaciji mogu biti bilo koji poredivi tipovi.  

Logički izrazi se grade i pomoću logičkih operacija    

! negacija, 
&& konjunkcija,
|| disjunkcija.

Operandi mogu biti isključivo logičkog tipa.


3. Operatori

Tipom podatka je između ostalog određen i skup operatora koji mogu da se koriste nad podacima datog tipa. Najčešće klasifikacije su: po broju operanada i u odnosu na vrstu izraza u kojima se koriste.

Operatori po broju operanada se dele na:

  • unarne,

  • binarne i

  • ternarne.

Unarni operatori su operatori koji imaju samo jedan operand. Binarni operatori se primenjuju nad dva operanda, a ternarni operator ima tri operanda i u programskom jeziku C# postoji samo jedan takav operator ("? :").

Po drugoj klasifikaciji operatori se mogu podeliti na:

  • aritmetičke (numeričke),

  • logičke,

  • relacijske i

  • operatore za rad sa tekstualnim podacima.

Aritmetički operatori su:

  • + (sabiranje)

  • - (oduzimanje)

  • * (množenje)

  • / (deljenje)

  • % (ostatak celobrojnog deljenja - moduo)

Logički operatori su:

  • ! - negacija

  • || - logičko "ILI" (OR)

  • && - logičko "I" (AND)

Relacijski operatori su:

  • == - ekvivalencija tj. jednakost

  • != - neekvivalencija tj. različito

  • < - manje

  • > - veće

  • <= - manje ili jednako

  • >= - veće ili jednako

Operatori za rad sa bitovima su:

  • ~ - negacija na nivou bita

  • & - I na nivou bita

  • | - ILI na nivou bita

  • ^ - ekskluzivno ILI na nivou bita

  • << - pomeranje u levo

  • >> - pomeranje u desno

Tekstualni operator je konkatenacija u oznaci + i predstavlja nadovezivanje drugog operanda na prvi operand.

Pored prethodno navedenih operatora, postoje i operatori dodele, operatori za inkrementiranje, operatori za dekrementiranje, ternarni operator itd.

Operatori inkrementiranja u oznaci ++ i dekrementiranja u oznaci -- mogu biti prefiksni (u složenijim izrazima se izvršavaju pre računanja vrednosti izraza) i postfiksni (u složenijim izrazima se izvršavaju tek nakon izračunatog izraza). Operator inkrementiranja povećava vrednost operanda za jedan, a operator dekrementiranja smanjuje vrednost operanda za jedan.

Prioritet operatora

Svi operatori se mogu svrstati u kategorije. Prioritet ovih kategorija je sledeći (od najvišeg ka najnižem):

  • osnovni operatori (pristup polju, poziv metode, pristup indeksu, postinkrementiranje, postekrementiranje, new, typeof, sizeof)

  • unarni operatori (i predekrementiranje i preinkrementiranje)

  • aritmetički (množenje, deljenje, ostatak pri deljenju)

  • sabiranje i oduzimanje

  • pomeranje na nivou bita (pomeranje u levo i pomeranje u desno)

  • relacioni operatori

  • jednakost (jednako i različito)

  • I na nivou bita

  • ekskluzivno ILI na nivou bita

  • ILI na nivou bita

  • logičko I

  • logičko ILI

  • ternarni operator

  • operatori dodeljivanja


4. ISTO kao u C

Naredbe koje se isto koriste kao u programskom jeziku C su:

  • if naredba,
  • while petlja,
  • do..while petlja,
  • switch - case,
  • for petlja
  • naredbe skoka
    • goto
    • continue
    • break

4.1. if naredba

if naredbom se implementira osnovni tip selekcije (grananja) kojom se vrši uslovno izvršenje jedne od dve moguće alternative.

Primer: Deo koda kojim se određuje veći od dva broja predstavljena promenljivama x i y i dodeljuje trećoj promenljivi veciBroj.

if (x > y)
    veciBroj = x;
else
    veciBroj = y;
Primer: Višestruko grananje. Kod koji određuje najveći od 3 broja predstavljena promenljivama x, y i z i upisuje u promenljivu najveciBroj.

if (x > y)
{
    if (x > z)
        najveciBroj = x;
    else
        najveciBroj = z;
}
else
{
    if (y > z)
        najveciBroj = y;
    else
        najveciBroj = z;
}


4.2. while petlja

while petlja ima opšti oblik:

while (<uslov>)
       <telo petlje>

<uslov> - predstavlja logički izraz koji može biti tačan ili netačan. Ako je uslov zadovoljen onda se izvršava telo petlje. Nakon izvršavanja poslednje naredbe u telu petlje opet se proverava uslov. while petlja se završava onog trenutka kada uslov više nije zadovoljen.

Primer:

int i = 5;
int suma = 5;
 
while (i <= 10)
{
    suma = suma + i;
    i++;
}
Console.WriteLine("Suma = " + suma);


4.3. do-while petlja

do-while petlja ima opšti oblik:

do
       <telo petlje>
while (<uslov>);

<uslov> - predstavlja logički izraz koji može biti tačan ili netačan. Ova petlja funkcioniše tako što se izvršava telo petlje a zatim se proverava uslov. Ako je uslov ispunjen onda se opet izvršava telo petlje, u suprotnom se završava petlja.

Primer:

int i = 0;
int suma = 0;
 
do
{
    suma = suma + i;
    i++;
} while (i <= 10);
Console.WriteLine("Suma = " + suma);

4.4. switch - case

Višestruko grananje je vrsta grananja kod koga postoji više alternativa koje mogu biti izvršene zavisno od toga koji uslovi su zadovoljeni. Broj uslova je dva ili više. Može se realizovati preko višestrukih if naredbi ili switch - case naredba.

Primer: Deo koda koji ispisuje ime meseca tekuci.

switch (tekuci)
{
    case 1:
        Console.WriteLine("Januar");
        break;
    case 2:
        Console.WriteLine("Februar");
        break;
    case 3:
        Console.WriteLine("Mart");
        break;
    case 4:
        Console.WriteLine("April");
        break;
    case 5:
        Console.WriteLine("Maj");
        break;
    case 6:
        Console.WriteLine("Jun");
        break;
    case 7:
        Console.WriteLine("Jul");
        break;
    case 8:
        Console.WriteLine("Avgust");
        break;
    case 9:
        Console.WriteLine("Septembar");
        break;
    case 10:
        Console.WriteLine("Oktobar");
        break;
    case 11:
        Console.WriteLine("Novembar");
        break;
    case 12:
        Console.WriteLine("Decembar");
        break;
}

U nekim slučajevima višestrukog grananja istu obradu treba izvršiti za više različitih vrednosti selektorskog izraza. U tim slučajevima se mogu spajati case linije.

Primer: Kod koji u promenljivu brojDana upisuje broj dana tekućeg meseca odnosno 0 ako tekući mesec nije korektno unet.

switch (tekuci)
{
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        brojDana = 31;
        break;
    case 2:
        brojDana = 28;
        break;
    case 4: case 6: case 9: case 11:
        brojDana = 30;
        break;
    default:
        brojDana = 0;
        break;
}



4.5. for petlja

for petlja je petlja sa konstantnim brojem prolaza i naziva se još i brojačka petlja. Opšti oblik for petlje u programskom jeziku C# je:

for (<izraz1>; <izraz2>; <izraz3>)
       <telo petlje>

<izraz1> - vrši inicijalizaciju promenljivih koje se koriste u petlji (može da bude postavljanje početne vrednosti brojača petlje)
<izraz2> - predstavlja uslov na osnovu koga se odlučuje da li će se telo petlje još izvršavati ili se izvršavanje petlje prekida (petlja se izvršava dok je vrednost ovog izraza tačna)
<izraz3> - definiše promenu vrednosti promenljivih koje se koriste u petlji. Navedena promena se vrši nakon svake iteracije
<telo petlje> - telo petlje predstavlja jedna naredba, struktura ili blok

Primer:

int[] niz = { 1, 2, 3, 4, 5 };
 
for (int i = 0; i < niz.Length; i++)
    Console.WriteLine("Element niza: " + niz[i]);


4.6. Naredbe skoka

U nekim situacijama je potrebno da se neki delovi koda "preskoče". Da bi se izmenio normalan tok izvršavanja naredbi mogu se koristiti sledeće naredbe:

  • goto

  • break

  • continue

goto naredba

Ova naredba omogućava bezuslovni skok na neku labelu koja je definisana u programu. Labela se u programu dobija tako što se iza nekog identifikatora stavlja dvotačka.

Primer:

class Primer
{
    public static void Main()
    {
        int ukupno = 0;
        int indeks = 0;
 
    ovoJeLabela:
        indeks++;
        ukupno += indeks;
        Console.WriteLine("Indeks = " + indeks);
        if (indeks < 5)
        {
            Console.WriteLine("goto ovoJeLabela");
            goto ovoJeLabela;
        }
        Console.WriteLine("Ukupno = " + ukupno);
    }
}
NAPOMENA: Ne smatra se dobrom programerskom praksom ako se koristi naredba goto. Ako ne morate, nemojte da je koristite!

break naredba

Korišćenjem break naredbe može se prekinuti bilo koja vrsta petlje.

Primer:

class Primer
{
    public static void Main()
    {
        int ukupno = 0;
 
        for (int indeks = 1; indeks <= 10; indeks++)
        {
            Console.WriteLine("Indeks = " + indeks);
            ukupno += indeks;
            if (indeks == 5)
            {
                Console.WriteLine("Prekid for petlje");
                break;
            }
        }
        Console.WriteLine("Ukupno = " + ukupno);
    }
}

continue naredba

Naredbom continue se ne prekida izvršenje petlje već se samo prekida tekuća iteracija i nastavlja se sa sledećom iteracijom. Tj. sve naredbe u telu petlje koje dolaze posle naredbe continue se preskaču i prelazi se na zaglavlje petlje.

Primer:

class Primer
{
    public static void Main()
    {
        int ukupno = 0;
 
        for (int indeks = 1; indeks <= 10; indeks++)
        {
            if (indeks == 6)
            {
                Console.WriteLine("continue naredba");
                continue;
            }
            Console.WriteLine("Indeks = " + indeks);
            ukupno += indeks;
        }
        Console.WriteLine("Ukupno = " + ukupno);
    }
}

5. ** Nabrojivi i strukturni tip **

Enumeracije ili nabrajanje tipa Enum u C# programskom jeziku


Enumerations - enumeracije su specijalni vrednosni tipovi podataka koji omogućava da zadate grupu imenovanih numeričkih konstanti. U Srbiji se enumeracija često naziva nabrajanje, ali onda je bolje da kažete nabrajanje tipa enum jer postoje i druge vrste nabrajanja u C# programskom jeziku.

Strukture u C# programskom jeziku


Struktura jeste slična klasi ali nije klasa, koristi se slično enumeracijama ali nije enumeracija jer nema nabrajanja. Najjednostavnije rečeno, struktura vam je vrednosni tip podataka koji služi da enkapsulirate manji skup podataka. Za razliku od klasa koji su referentni tip i koji se kreiraju na hipu, strukture se kreiraju na steku i sve dok je struktura mala, upravljanje memorijom koja upravlja hipom je znatno smanjeno. Možete se pitati zašto je to bitno, zar sad treba da razmišljate i o memoriji dok programirate. U principu uvek treba u programiranju da razmišljate o memoriji bez obzira koliko je imate u računaru. Da bi vam bilo jasnije, treba da znate da je memorija računara definisana u tri segmenta. U tekst ili kod segment, stek segment i hip segment.


( Strukture su vrednosni tip podataka )
 

Kad npr. otvorite *.exe datoteku, sav taj mašinski, ljudski nečitljiv kod se stavlja u tekst segment ili kako ga češće zovu kod segment memorije. Stek segment se uglavnom koristi za čuvanje privremenih podataka, često u obliku promenjivih i automatskih metoda, dok se hip segment više koristi za različite svrhe programa s obzirom da se bavi dinamičkom raspodelom memorije. U hip segmentu memorije, obrazac raspodele memorije nije poznat tokom izvršavanja memorije. Ono što je najbitnije da upamtite je da se stek segment brže izvršava od hip segmenta ali je zato stek segment memorije manji i skuplji.


5.1. Enumeracije

Enumerations - enumeracije su specijalni vrednosni tipovi podataka koji omogućava da zadate grupu imenovanih numeričkih konstanti.

Kada hoćete da deklarišete enumeraciju u C# programskom jeziku; koristite ključnu reč enum izvan funkcija kao što to radite sa strukturama.

enum  ime_enumeracije
{
vrednost1;     vrednost2;     … }

Jednom kad ste deklarisali enumeraciju, možete da je koristite na tačno isti način kao i bilo koji drugi numerički tip podataka. Vrednostima enumeracije možete dodeljivati jedino celobrojnu vrednost. Ukoliko želite vrednostima enumeracije da dodeljujete vrednosti tipa stringova, onda bolje razmislite o tome da koristite strukturu u kojoj će nabrajanje biti jedan od članova strukture.

Kako se dodeljuju vrednosti strukturi enumeracija?

Jednostavno, ako vrednostima niste dodelili nikakvu celobrojnu vrednost, onda se podrazumeva da nabrajanje počinje od 0 kao i u nizovima.
enum  ime_enumeracije
{
vrednost1 = 0;     vrednost2 = 1;     … }

Međutim ukoliko vi dodate neku vašu celobrojnu vrednost, posle nje će svaka vrednosti biti uvećana za 1. Npr.
enum  ime_enumeracije
{
vrednost1 = 1;     vrednost2;     … }
To znači da je u ovom slučaju vrednost2 jednaka 2, sledeća vrednost bi imala vrednost 3 itd. Vi možete imati iste vrednosti u stavkama enumeracije ali ne vidim poentu zašto bi ste to radili. Enumeracije su po defaultu tipa integer ali vi možete to promeniti u drugi celobrojni tip podataka.
enum ime_enumeracije : byte { ... }

5.2. Strukture

Struktura se deklariše kao i enumeracija ili klasa, samo što koristi ključnu reč struct. Sintaksa strukture je:

Struct ime_strukture 
{
       članovi_strukture;
};

Članovi strukture mogu imati pored promenjivih i metode i čak konstruktore. Strukture jesu izvedene iz klase Object, ali one ne mogu da vrše nasleđivanje. To u prevodu znači da struktura ne može da sadrži druge strukture ili klase. Vi ne možete imati konstruktor u strukturi koji ne uzima ni jedan parametar. On već postoji i implicitno inicijalizuje na nulu sva polja u strukturi. Struktura ne može da sadrži destruktor. Vi ne morate da koristite ključnu reč new da instacirate članove strukture ali nije zabranjeno. To takođe ne znači da ćete sa ključnom rečju new prebaciti deo memorije strukture sa steka na hip. Struktura se isključivo formira u stek segmentu.

Razlika između Struct i Class u C# programskom jeziku

Često pitanje u OOP načinu programiranju jeste koja je zapravo razlika između strukture i klase.

Prvo ću krenuti sa strukturom, struktura u C# programskom jeziku je value type što znači da se njena alokacija se uvek nalazi na steku (stack).
Klasa za razliku od strukture svoju alokaciju ima na heap-u tj. u dinamičkoj dijelu memorije, u potpuno drugom logičkom djelu memorije u odnosu na stek.

U primeni, strukturu ćemo najčešće naći kada radimo sa manjim tipovima podataka i manjim količinama podataka, glavni razlog ove "odluke" jeste taj što ona uveliko utiče na performanse naše App (aplikacije). Ako se vodimo predhodno naučenim pojmom čuvanja strukture na steku, imamo pojavu da kada želimo poslati strukturu u neku od funkcija, mi zapravo tada šaljemo čitavu strukturu i njen sadržaj. Iz ovog možemo zaključiti da u runtime-u imamo proces kompletnog kopiranja objekta onoliko puta koliko pozivamo funkcija koje kao parametar preuzimaju našu strukturu, računica i zaključak je jednostavan: u slučaju veće strukture imamo mnogo veće vreme izvršavanja koje uglavnom ide na kopiranje svih informacije iz strukture u njenu lokalnu kopiju.

Važno za napomenuti je da je stek mnogo manja logička količina memorija u odnosu na heap, i proces slanja strukture kroz funkcije duplo povećava zauzeće memorije na steku. Još jedna bitna stvar je da u funkciji mi radimo sa kopijom objekta koji je poslat pri pozivu funkcije i svaku promenu koju želimo raditi moramo na adekvatan način uraditi i na "glavnom" objektu.

Kada uzmemo u obzir čitav proces kopiranja shvatimo koliko je ovo "skupo" za našu App... Ako ovaj isti primer primenimo na klase koje su reference type, iz jednog mini testa koji ćemo uraditi u sledećim koracima...dolazimo do zaključka da se klase uvek šalju po referenci tj. u funkciju koja prima našu klasu mi šaljemo adresu našeg objekta u dinamičkoj memoriji i samim tim mi nemamo potrebu za kopiranjem onoga što se nalazi u klasi, a sa ugla performansi šaljemo mnogo manju informaciju (za razliku do strukture i slanja čitavog objekta). Kada prosledimo adresu (referencu) mi u funkciji direktno pristupamo toj memorijskoj lokaciji i radimo potrebne izmene nad našim objektom.

Malo objašnjenje za predhodne pojmove u slučaju da nisu jasne stvari oko adresa. Svaki vaš objekat koji je smešten u memoriji ima svoju memorijsku adresu tj. lokaciju na kojoj se nalazi. Kada vi imate informaciju tj. adresu na kojoj je vaš objekat vi imate "pravo" i mogućnost da ga direktno editujete... mnogo će biti jasnije u sledećem primeru:

Na slikama ispod vidite kako izgleda naša struktura pod imenom "TackaKoordinateStruktura", njeni atributi i konstruktor:


kao i kod na kojem je definisana naša klasa "TackaKoordinateKlasa", atributi i konstruktor:


Kao što i vidite skoro da su identične, jedina razlika na prvi pogled je u ključnim rečima class i struct. Ali naravno velika je razlika u pozadini, a to ćemo upravo dokazati na sledeći način:

Za potrebu ovoga mini testa koristit ćemo dve funkcije koje kao parametar primaju strukturu i klasu, naravno jedna prima strukturu, a druga klasu i izgledaju ovako;


A u main funkciji imamo sledeću situaciju:


Ako pokrenemo naš program možemo očekivati sledeći ispis na konzoli:


Ako pažljivo pratimo ispis na konzoli, možemo primetiti da se vrednost atributa naše strukture promeni samo u funkciji PromjenaStanjaStrukture(), kada se završila funkcija u mainu imamo informaciju da je vrednost atributa strukture ista kao i pre poziva. Iz ovoga možemo zaključiti samo jedno, da je naša struktura po svojoj prirodi poslata u funkciju po vrednosti i da smo u funkciji radili i vršili promene sa njenom kopijom koja je naravno uništena pri završetku funkcije (silazak sa steka).

Sa druge strane ako posmatramo ponašanje naše klase, pri inicijalizaciji je dobila vrednosti (7, 12), te u funkciji PromjenaStanjaKlase(), kao što je i definisano dobija vrednosti (20, 7), posle završetka sledi ispis koji nam ispisuje one vrednosti koje je klasa dobila u funkciji. Objašnjenje ovoga je da se klase uvek šalju po referenci, a ne po vrednosti kao što to strukture rade. Funkcija PromjenaStanjaKlase() dobila je adresu naše klase i mogla je direktno da utiče na promenu njenih atributa tj. modifikovali smo originalni objekat.

Iz ovog mini testa i primera dokazali smo i zaključili da se strukture uvijek šalju po vrednosti, a klase po referenci i ovo nam ujedno i govori pravu razliku između strukture i klase u C# programskom jeziku.

6. DRUGAČIJE nego u C

  • foreach (varijacija for petlje )
  • stringovi (realizovani kao objekti)
  • Nizovi

6.1. foreach petlja

Opšti oblik foreach petlje je:

foreach (tip promenljiva in izraz)
          telo petlje

promenljiva je promenljiva koja se koristi u petlji za pristup svim elementima specificiranim u izrazu izraz.

Primer:

int[] nekiNiz = { 1, 5, 2, 7, 3 };
 
foreach (int element in nekiNiz)
    Console.WriteLine("Element niza je = " + element);


6.2. Stringovi u C#

jeziku C#, tip string (alijas tipa System.String) predstavlja nepromenljivu sekvencu Unicode znakova. Literal tipa string zadaje se unutar navodnika:

string a = “Heat”;
string je referentni tip a ne vrednosni. Međutim, njegovi operatori jednakosti slede semantiku vrednosnih tipova:

string a = “test”, b = “test”;
Console.Write (a == b); // True
Za kreiranje stringa u programskom jeziku C# koristi se .NET klasa Object.String pa se ključna reč string u stvari odnosi na klasu System.String

// Deklarisanje bez inicijalizacije.
string tekst1;
// Inicijalizacija na null.
string tekst2 = null;
// Inicijalizacija na prazan string.
// Koristi Empty umesto "".
string tekst3 = System.String.Empty;
//Inicijalizacija konstantnim stringom
string putanja= "c:\\Program Files\\Microsoft Visual Studio 8.0";
// System.String 
System.String zdravo = "Hello World!";
// Implicitna deklaracija
var temp = "I'm still a strongly-typed System.String!";
// Korišćenjem String konstructora
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);
Operator + nadovezuje dva znakovna niza. Jedan od operanada ne mora biti znakovni niz.

string s = “a” + “b”;
string s = “a” + 5; // a5

Tip string ne podržava operatore poređenja < i >. Umesto njih morate koristiti metodu CompareTo tipa string, koja vraća pozitivan broj, negativan broj ili nulu, zavisno od toga da li je prva vrednost po redosledu iza, ispred ili na mestu druge vrednosti.
Metode IndexOf i LastIndexOf traže znak unutar zadatog znakovnog niza. Metode Contains, StartsWith i EndsWith traže podniz u zadatom znakovnom nizu.
Pošto je tip string nepromenljiv, sve metode koje „manipulišu“ znakovnim nizom vraćaju nov niz, ostavljajući originalni nedirnut:
• Substring izdvaja deo znakovnog niz
• Insert umeće znakove na zadato mesto, a Remove ih uklanja odatle.
• PadLeft i PadRight dodaju beline.
• TrimStart, TrimEnd i Trim uklanjaju beline.

Klasa string definiše i metode ToUpper i ToLower za promenu malih slova u velika i obrnuto, metodu Split koja deli znakovni niz na podnizove (na osnovu zadatih graničnika), i statičku metodu Join – za ponovno spajanje podnizova u znakovni niz.


6.3. Nizovi i matrice u C#

Kreiranje niza u programskom jeziku C# :

// deklarisanje niza sa dve naredbe
tip[] niz;
niz = new tip[duzina];
// deklarisanje niza jednom naredbom
tip[] niz = new tip[duzina];
Za kreiranje niza C# iza scene kreira objekat klase Array iz .NET Framework-a pa otuda i operator new u deklaraciji.
Po kreiranju niza svaki element niza se inicijalizuje na podrazumevane vrednosti zavisno od tipa elementa:
- numerički na 0
- char na '\0'
- Boolean na false
- DateTime na 01/01/0001 00:00:00
- pokazivački tip na null

Sam niz je uvek objekat pokazivačkog tipa, nezavisno od toga kojeg su tipa elementi. Na primer, sledeća naredba je ispravna:

int[] a = null;

Inicijalizacija elemenata niza:

tip[] niz1 = new tip[duzina] {vrednost1, vrednost2, vrednost3,...};
// bez navodjenja duzine
tip[] niz1 = new tip[] {vrednost1, vrednost2, vrednost3,...};
// bez navodjenja tipa i duzine
tip[] niz2 = {vrednost1, vrednost2, vrednost3,..., vrednostN};
// Npr.
char[] samoglasnici = new char[] {‘a’,’e’,’i’,’o’,’u’};
// ili, jednostavno:
char[] samoglasnici= {‘a’,’e’,’i’,’o’,’u’};

Zbog toga što su nizovi izvedeni iz klase Array, na raspolaganju su:
- svojstvo Length koje daje broj elemenata niza
- metoda BinarySearch(niz, vrednost) koja daje indeks elementa određene vrednosti
- metoda Sort(niz) koja vrši sortiranje niza u rastući redosled

Matrice

U deklaracijama pravougaonih nizova, zarezi razdvajaju svaku dimenziju. Metoda GetLength niza vraća dužinu zadate dimenzije (počevši od 0):

int[,] matrix = new int [3, 3];
for (int i = 0; i < matrix.GetLength(0); i++)
  for (int j = 0; j < matrix.GetLength(1); j++)
    matrix [i, j] = i * 3 + j;

Inicijalizacija matrice

int[,] matrix = new int[,]
{
 {0,1,2},
 {3,4,5},
 {6,7,8}
};

Nazubljeni nizovi (jagged arrays)
Nazubljeni nizovi se deklarišu pomoću uzastopnih ugaonih zagrada koje predstavljaju svaku dimenziju niza. U sledećem primeru deklariše se nazubljen dvodimenzioni niz čija je najveći broj redova 3

Broj kolona nije zadat u deklaraciji jer – za razliku od pravougaone matrice – svaki unutrašnji niz može biti proizvoljne dužine - broja kolona. Svaki unutrašnji niz se implicitno inicijalizuje na vrednost null a ne na prazan niz. Svaki unutrašnji niz mora se napraviti ručno:

int[][] matrix = new int[3][];
for (int i = 0; i < matrix.Length; i++)
{
  matrix[i] = new int [3]; // Izrada unutrašnjeg niza
  for (int j = 0; j < matrix[i].Length; j++)
    matrix[i][j] = i * 3 + j;
}