Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Prosleđivanje parametara po vrednosti i po referenci u C#

[es] :: .NET :: Prosleđivanje parametara po vrednosti i po referenci u C#

[ Pregleda: 5119 | Odgovora: 3 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Laki123

Član broj: 16706
Poruke: 98
*.adsl-a-1.sezampro.yu.



+4 Profil

icon Prosleđivanje parametara po vrednosti i po referenci u C#29.07.2008. u 16:01 - pre 191 meseci
Na strani http://www.elitesecurity.org/t325268-Pointeri-JAVA-ili-JAVI vodila se zanimljiva rasprava o tome kako java prosleđuje parametre. Neki su tvrdili da java reference prosleđuje po referenci, a neki su tvrdili da se reference prosleđuju samo po vrednosti. Ovi drugi su bili u pravu pošto se u Javi sve prosleđuje po vrednosti.
Zabunu je izazvalo to, što kada se kaže prosleđivanje po vrednosti, očekuje se da promenljiva koju smo prosledili ostane ne promenjena, pošto se funkciji šalje kopija te promenljive. Ali kada se referenti tip šalje funkciji, i u funkciji ga izmenimo, te promene će ostati.
Stvar je u tome što se u ovom slučaju ne pravi kopija samog objekta, nego se pravi kopija reference koja pokazuje na taj objekat. Znači mi ustvari funkciji šaljemo kopiju reference.
Dakle Java podržava prosleđivanje samo po vrednosti, dok C# podržava prosleđivanje i po referenci. Po defaultu C# prosleđuje promenljive po vrednosti (isto kao i Java), a da bi prosleđivao po referenci dodaje se još ref.
Na kraju najbolje da se sve ovo pokaže jednim primerom.
Code:

    class Program
    {
        static void Main(string[] args)
        {
            Koordinata mojaKoordinata = new Koordinata(0, 0); //objedat koji cemo menjati po vrednosti
            Koordinata mojaKoordinataRef = new Koordinata(0, 0); //objedat koji cemo menjati po referenci
            int mojBroj = 0; //broj koji cemo menjati po vrednosti
            int mojBrojRef = 0; //broj koji cemo menjati po referenci
            Console.WriteLine("Pre izmene:");
            PrikazTeksta(mojaKoordinata, mojaKoordinataRef, mojBroj, mojBrojRef); //prikazuje vrednosti za sve promenljive
            Menjaj(mojaKoordinata, ref mojaKoordinataRef, mojBroj, ref mojBrojRef);
            Console.WriteLine("Posle izmene:");
            PrikazTeksta(mojaKoordinata, mojaKoordinataRef, mojBroj, mojBrojRef);
            IzmenaObjekta(mojaKoordinata, ref mojaKoordinataRef); //postavlja objekte na null
            Console.WriteLine("Izmena koordinata:");
            Console.WriteLine("Da li je koordinata null: po vrednosti je " + (mojaKoordinata == null).ToString() + " po referenci je " + (mojaKoordinataRef == null).ToString());
            Console.Read(); //da nam se ne zatvori ekran :)
        }

        static void PrikazTeksta(Koordinata koord, Koordinata koordRef, int a, int b)
        {
            Console.WriteLine("Koordinata je " + koord.vrednostX.ToString() + "," + koord.vrednostY.ToString() + " po referenci je " + koordRef.vrednostX.ToString() + "," + koordRef.vrednostY.ToString());
            Console.WriteLine("Broj je " + a.ToString() + " po referenci je " + b.ToString());
        }

        static void Menjaj(Koordinata koord, ref Koordinata koordRef, int a, ref int b)
        {
            koord.vrednostX = 5;
            koord.vrednostY = 5;
            koordRef.vrednostX = 5;
            koordRef.vrednostY = 5;
            a = 5;
            b = 5;
            Console.WriteLine("Za vreme izmene:");
            PrikazTeksta(koord, koordRef, a, b);
        }

        static void IzmenaObjekta(Koordinata koord, ref Koordinata koordRef)
        {
            koord = null;
            koordRef = null;
        }
    }

    class Koordinata
    {
        int x, y;
        public Koordinata(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public int vrednostX
        {
            get { return x; }
            set { x = value; }
        }
        public int vrednostY
        {
            get { return y; }
            set { y = value; }
        }
    }


Dobijamo sledeći rezultat:
Code:

Pre izmene:
Koordinata je 0,0 po referenci je 0,0
Broj je 0 po referenci je 0
Za vreme izmene:
Koordinata je 5,5 po referenci je 5,5
Broj je 5 po referenci je 5


Zasad je sve bilo jasno, ali da vidimo sledeći rezultat
Code:

Posle izmene:
Koordinata je 5,5 po referenci je 5,5
Broj je 0 po referenci je 5


Prvi red, zar ne bi trebalo da je prva vrednost ostala 0,0?
Ne, jer kao što sam na početku rekao mi prosleđujemo kopiju reference, koja i dalje pokazuje na isti objekat.
Mi smo u funkciji Menjaj izmenili objekat, pa ove dve različite reference pokazuju na taj izmenjen objekat.
Code:

Izmena koordinata:
Da li je koordinata null: po vrednosti je False po referenci je True


Na kraju smo u funkciji IzmenaObjekta, prosledili jedan parametar po vrednosti, a drugi po referenci, i oba postavili da budu null.
U prvom slučaju pravimo kopiju reference, tu kopiju postavljamo na null, pa po izlasku iz funkcije, original je ostao ne promenjen, tj. nije null.
U drugom slučaju se ne pravi kopija pa će referenca ostati izmenjena.
 
Odgovor na temu

Laki123

Član broj: 16706
Poruke: 98
*.adsl-a-1.sezampro.yu.



+4 Profil

icon Re: Prosleđivanje parametara po vrednosti i po referenci u C#29.07.2008. u 16:04 - pre 191 meseci
Ukoliko bi u funkciji Menjaj umesto
Code:

koord.vrednostX = 5;
koord.vrednostY = 5;
koordRef.vrednostX = 5;
koordRef.vrednostY = 5;

stavili
Code:

Koordinata nova = new Koordinata(5, 5); //pravimo novi objekat sa vrednostima x=5 i y=5
koord = nova;
koordRef = nova;

Sada će se prosleđeni parametri ponašati baš kao što smo na početku očekivali (rezultat će biti 0,0 i 5,5).
U prvom slučaju se nije promenila vrednost objekta, a u drugom jeste, zato što smo u prvom slučaju koristili kopiju reference.

Dakle da zaključim, u C#, ne prosleđujemo objekte, već reference na objekte.

Znam da se o ovome već raspravljalo u sličnim temama, ali sam mislio da nije loše da se to sve objedini u jednoj temi.
 
Odgovor na temu

Aleksandar Ružičić
Software Architect, Appricot d.o.o.
Beograd

Član broj: 26939
Poruke: 2881

Jabber: krckoorascic@gmail.com
Sajt: krcko.net


+44 Profil

icon Re: Prosleđivanje parametara po vrednosti i po referenci u C#29.07.2008. u 17:01 - pre 191 meseci
Citat:
Laki123: ...
Dakle da zaključim, u C#, ne prosleđujemo objekte, već reference na objekte.
...


ne samo c# vec bilo koji jezik koji pored value tipova ima i referentne tipove, jer mnogo je lakse/efikasnije/brze prosledjivati referencu (pointer na stvarni objekat) nego gurnuti celu strukturu na stek.

cak i by-value nacinom prosledjivanja prosledjujemo referencu a ne stvarni objekat/strukturu (samo sto u byval slucaju referenca je na kopiju stvarnog objekta, tj bar bi tako trebalo al eto java ne funkcionise na taj nacin... mada ko jos pametan i koristi javu :p)
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Prosleđivanje parametara po vrednosti i po referenci u C#03.08.2008. u 09:51 - pre 191 meseci
Imate bas detaljnu raspravu o C++/Java/.NET prosledjivanju parametara i sta je sta i sta moze/ne moze.

http://www.elitesecurity.org/t...ledjivanje-reference-upucivaca
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

[es] :: .NET :: Prosleđivanje parametara po vrednosti i po referenci u C#

[ Pregleda: 5119 | Odgovora: 3 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.