Forum » Programiranje » C# je mozna referenca do int izven funkcije (direkt v classu torej)
C# je mozna referenca do int izven funkcije (direkt v classu torej)
Vapo1 ::
class ZunanjiClass { public int ZunanjiClassInt = 5; } class MojClass { int i; public void SetInteger(ref int ii) { this.i = ii; } public void DisplayInt() { MessageBox.Show(this.i.ToString()); } } void MAIN() { ZunanjiClass ZC = new ZunanjiClass(); MojClass MC = new MojClass() MC.SetInteger(ref ZC.ZunanjiClassInt); MC.DisplayInt(); //izpise 5 ZC.ZunanjiClassInt++; MC.DisplayInt(); //izpise 6 ZC.ZunanjiClassInt++; MC.DisplayInt(); //izpise 7 ZC.ZunanjiClassInt++; MC.DisplayInt(); //izpise 8 int x = 300; MC.SetInteger(ref x); MC.DisplayInt(); //izpise 300 x++; MC.DisplayInt(); //izpise 301 x++; MC.DisplayInt(); //izpise 302 }
no.. iz kode je razvidno kaj bi rad - rad bi da je integer i v MojClass-u referencnega tipa
-kako to dosezem? - ta koda gor ne deluje namrec ker:
public void SetInteger(ref int ii) { this.i = ii; }
ker ta funkcija skopira ii v i - in ne nastavi reference(to kar bi hotel).... drugace se integer ii znotraj SetInteger funkcije obnasa tako kot hocem (je referencnega tipa) jaz bi rad samo to obnasanje extendal tudi zunaj te funkcije na celoten MojClass preko integerja i
obstaja veliko poti okoli tega - lahko naredim nek svoj class in notri dam ta int in potem ta class ki je reference type okoli posiljam
ampak vseeno me zanima ce se da to narediti v temu tipu oblike kot je zgornja koda...
gledal sem tudi kako je z pointerji ampak se mi zdi da je porblem spet ta da je unsafe keyword nekako spet samo za pointerje znotraj funkcije aplikabilen - in ne za celoten class - ce bi se nekako dalo narediti celoten class unsafe in imeti in imeti unsafe pointer polja v classu bi najbrz lahko dosegel to kar hocem..
hvala
Tutankhamun ::
Mogoče kej tazga
class MyVar { public int ii; } class MyClass { public void SetVar(MyVar var) { myvar = var; } public int GetInt() { return myvar.ii; } private MyVar myvar; } static void Main(string[] args) { MyVar var = new MyVar(); var.ii = 5; MyClass my = new MyClass(); my.SetVar (var); var.ii = 10; Console.WriteLine(my.GetInt()); }
AMD Phenom QUAD 9950 Black Edition, 8GB
Vapo1 ::
ja to je ta fora da vrzem int v nek class (v tem primeru MyVar)(ki je seveda reference type) in potem okoli posiljam ta class s tem integerjem notir... ok....
ampak mene se vedno zanima ce se da narediti reference type integer ki ni samo znotraj funkcije -
ce naredimo takole je vse ok:
ok... ampak.. a nebi mogli zdaj nekako narediti nekaj takega:
- torej da bi se ta referenca iz ii prenesla se naprej na i in da bi potem manipulacije i-ja se poznale tudi na ii-ju ... in da bi se poznalo tudi zunaj classa na temu integerju - (od koderkoli ze se je podalo ta integer (torej ko je nekaj poklicalo metodo SetVar(ref nekZunanjiInteger); )
ampak mene se vedno zanima ce se da narediti reference type integer ki ni samo znotraj funkcije -
ce naredimo takole je vse ok:
public void SetVar(ref int ii) { //lahko tukaj notri ii uporabljamo kot normalen int .. pa vendar je reference type in se bo vse kar tukaj naredimo temu integerju poznalo tudi tam zunaj od koder je ta referenca prisla }
ok... ampak.. a nebi mogli zdaj nekako narediti nekaj takega:
class MyClass { ref int i; //tole compiler ne prebavi ... ampak nekaj v tem smislu bi se moralo dati public void SetVar(ref int ii) { this.i = ref ii; } }
- torej da bi se ta referenca iz ii prenesla se naprej na i in da bi potem manipulacije i-ja se poznale tudi na ii-ju ... in da bi se poznalo tudi zunaj classa na temu integerju - (od koderkoli ze se je podalo ta integer (torej ko je nekaj poklicalo metodo SetVar(ref nekZunanjiInteger); )
Zgodovina sprememb…
- spremenilo: Vapo1 ()
HellRaiseR ::
To je seveda možno, le ref-a pri delaraciji ne potrebuješ. Naprimer:
class MainClass { public static void Main(string[] args) { int i = 1; SetVar(ref i); Console.Write(i); } private static void SetVar(ref int i) { i = 5; } }
Zgodovina sprememb…
- spremenil: HellRaiseR ()
TopCat ::
To namenoma ni mogoče. Gre se za to, da value types niso pod kontrolo GC-ja. Če bi bilo to mogoče bi se lahko zgodilo kaj takega: V razredu A definiraš nek int, ga pošlješ v razred B in tam manipuliraš z njim. Medtem bi GC ugotovil, da na razred A ne kaže več nobena referenca in bi ga sprostil ... Kaj bi se zgodilo? Razred B bi pisal kar nekam v pomnilnik, kar je pa zelo huda napaka ...
fiction ::
No ja, problem je v tem, da so podatki vedno "del" razreda. Ce hoces kako drugace scarati je to po vsej verjetnosti narobe oz. vsaj proti nacelom objektno orientiranega programiranja. Zato tudi nimas globalnih spremenljivk ali cesa takega.
Pri "value type" gre za to, da so tisto tam res dejanski podatki. Ce bi imel npr. "reference type" bi bili podatki drugje, ti pa bi hranil le referenco tja (se pravi nek "kazalec" na podatke). Poanta je v tem, da ko naredis kopijo v bistvu pustis podatke take kot so, ustvaris le dodatno povezavo do njih. Tudi garbage-collection objekta je cisto neproblematicen. Takrat je samo ena povezava manj in ko nobeden vec ne kaze na podatke se tudi tisti pomnilnik sprosti (tukaj so recimo podatki le implicitno del objekta).
Kljucna beseda "ref" je misljena za klic funkcije. In sicer, da se tisti parameter prenasa "po referenci" in ne "po vrednosti". "Po vrednosti" pomeni, da se ob klicu funkcije kot argument naredi _kopija_ parametra. Pri "ref" je razlika samo to, da se to ne naredi (ampak se uporabi originalna spremenljivka). Ni pa zaradi tega "value type" int postal kar naenkrat "reference type"! Ko tisto v funkciji prirejas nekam naprej spet samo skopiras vrednost v drugo spremenljivko. Torej najvec kar lahko naredis je, da v funkciji kot ref paramater dejansko uporabljas oz. spreminjas atribut razreda.
Pri C# nimas tako kot v Javi Integer in int. Lahko pa naredis svoj "reference type" kot wrapper okrog int-a, ali pa sam alociras nek prostor za stevilko na kopici in potem okrog kopiras ta pointer. Kot sem ze prej omenil je v bistvu oboje precej podobno, le da je tisto drugo bolj nevarno, ker moras vedeti kaj delas.
Pri "value type" gre za to, da so tisto tam res dejanski podatki. Ce bi imel npr. "reference type" bi bili podatki drugje, ti pa bi hranil le referenco tja (se pravi nek "kazalec" na podatke). Poanta je v tem, da ko naredis kopijo v bistvu pustis podatke take kot so, ustvaris le dodatno povezavo do njih. Tudi garbage-collection objekta je cisto neproblematicen. Takrat je samo ena povezava manj in ko nobeden vec ne kaze na podatke se tudi tisti pomnilnik sprosti (tukaj so recimo podatki le implicitno del objekta).
Kljucna beseda "ref" je misljena za klic funkcije. In sicer, da se tisti parameter prenasa "po referenci" in ne "po vrednosti". "Po vrednosti" pomeni, da se ob klicu funkcije kot argument naredi _kopija_ parametra. Pri "ref" je razlika samo to, da se to ne naredi (ampak se uporabi originalna spremenljivka). Ni pa zaradi tega "value type" int postal kar naenkrat "reference type"! Ko tisto v funkciji prirejas nekam naprej spet samo skopiras vrednost v drugo spremenljivko. Torej najvec kar lahko naredis je, da v funkciji kot ref paramater dejansko uporabljas oz. spreminjas atribut razreda.
Pri C# nimas tako kot v Javi Integer in int. Lahko pa naredis svoj "reference type" kot wrapper okrog int-a, ali pa sam alociras nek prostor za stevilko na kopici in potem okrog kopiras ta pointer. Kot sem ze prej omenil je v bistvu oboje precej podobno, le da je tisto drugo bolj nevarno, ker moras vedeti kaj delas.
Vapo1 ::
ok... TopCat-ov odgovor mi vse pojasni.... "niso pod kontrolo GC" ..... najbrz je veliko razlogov zakaj value types niso pod GC ... najverjetneje bi bila huge razlika v hitrosti kode ce bi bili
ampak ok... torej ce rabim referencnega tipa int moram pac narediti svojega.... recimo:
tole sem dobil iz tu:
http://www.c-sharpcorner.com/UploadFile...
(kul clanek)
dajtmo ga zdaj se upgradeat z operatorji in "cast forami" da se bo dejansko dalo z njim pisati kodo kot z navadnim integerjem
--- cilj je da lahko potem nakoncu uporabljam MyInt takole nekako:
ampak ok... torej ce rabim referencnega tipa int moram pac narediti svojega.... recimo:
tole sem dobil iz tu:
http://www.c-sharpcorner.com/UploadFile...
(kul clanek)
public class MyInt { public int MyValue; } public MyInt AddFive(int pValue) { MyInt result = new MyInt(); result.MyValue = pValue + 5; return result; }
dajtmo ga zdaj se upgradeat z operatorji in "cast forami" da se bo dejansko dalo z njim pisati kodo kot z navadnim integerjem
public class MyInt { public int MyValue; //nevem kako tocno to gre public static int operator +(MyInt mi) { return mi.MyValue+this.MyValue; } public static implicit operator int(MyInt mi) { return mi.MyValue; } //nevem ce je to vse prav.... in keri operatorji se kaj manjkajo }
--- cilj je da lahko potem nakoncu uporabljam MyInt takole nekako:
void funkcija() { MyInt mi = new MyInt(); mi = 5; int i = 3; mi = mi + 3; mi += i; mi++; int x = mi; //in tako naprej... skrakta da se obnasa ko obicni int.... da ni treba non stop pikice nabijat(torej mi.MyValue neskoncnokrat) }
TopCat ::
Najbolj enostavna implementacija bi bila, da bi v tvojem razredu implementiral implicitno castanje v obe smeri. Ostalih operatorjev v tem primeru nebi bilo potrebno implementirat, saj bi prevajalnik sam poskrbel za pretvorbo v int in nazaj ...
Ima pa ta način en problem. Ob uporabi se generira kup začasnih objektov, kar bi slabo vplivalo na performace (pa tudi tvoj prvi primer nebi delal, saj bi nastajali novi objekti z novimi referencami). Splača se ti implementirati vsaj osnovne operatorje, ki spreminjajo vrednost objekta v vseh okusih:
* unarni: ++, --, -
* binarni: +,-, *, /
Seveda operatorjev je še več, ti so najbolj osnovni ...
Kako implementirati?
Unarni:
Binarni (jasno ne pozabi, da lahko seštevaš tudi MyInt in int, zato sta dve funkciji za vsak operator):
Jaz bi ti priporočal, da vsaj na začetku implementiraš castanje eksplicitno, tako da vidiš kateri operatorji ti še manjkajo ...
class MyInt { private int _value; public static implicit operator int(MyInt myInt) { return myInt._value; } public static implicit operator MyInt(int value) { return new MyInt { _value = value }; } }
Ima pa ta način en problem. Ob uporabi se generira kup začasnih objektov, kar bi slabo vplivalo na performace (pa tudi tvoj prvi primer nebi delal, saj bi nastajali novi objekti z novimi referencami). Splača se ti implementirati vsaj osnovne operatorje, ki spreminjajo vrednost objekta v vseh okusih:
* unarni: ++, --, -
* binarni: +,-, *, /
Seveda operatorjev je še več, ti so najbolj osnovni ...
Kako implementirati?
Unarni:
public static MyInt operator ++(MyInt myInt) { myInt._value++; return myInt; }
Binarni (jasno ne pozabi, da lahko seštevaš tudi MyInt in int, zato sta dve funkciji za vsak operator):
public static MyInt operator +(MyInt x, MyInt y) { x._value += y._value; return x; } public static MyInt operator +(MyInt x, int y) { x._value += y; return x; }
Jaz bi ti priporočal, da vsaj na začetku implementiraš castanje eksplicitno, tako da vidiš kateri operatorji ti še manjkajo ...
TopCat ::
Pa tudi če implementiraš vse operatorje boš imel težave z novimi objekti ...
Lahko narediš pretvorbo iz int v MyInt eksplicitno in dodaš funkcijo Assign, potem pa bi zgledalo nekako takole:
Torej v obeh primerih ko se ustvari nov objekt, to narediš eksplicitno in se zavedaš, da ti to lahko vpliva na delovanje programa ...
MyInt x = 12; // ustvari se prvi objekt x += 3; x = 14; // ustvari se drugi objekt int y = 4; x = y; // ustvari se tretji objekt.
Lahko narediš pretvorbo iz int v MyInt eksplicitno in dodaš funkcijo Assign, potem pa bi zgledalo nekako takole:
MyInt x = (MyInt)12; // ustvari se prvi objekt x += 3; x.Assign(14); int y = 4; x = (MyInt)y; // ustvari se drugi objekt.
Torej v obeh primerih ko se ustvari nov objekt, to narediš eksplicitno in se zavedaš, da ti to lahko vpliva na delovanje programa ...
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [Java] array v voiduOddelek: Programiranje | 2301 (2000) | Spura |
» | [java]problem z ThrowsOddelek: Programiranje | 1607 (1136) | killa bee |
» | Java metode;Oddelek: Programiranje | 4962 (4154) | ragezor |
» | [Java] Objekt poslan k metodi v kakšnem stanju?Oddelek: Programiranje | 1560 (1007) | shadeX |
» | [C#] DeserializacijaOddelek: Programiranje | 1867 (1470) | Cvenemir |