|
[ Zevs85 @ 17.09.2006. 23:39 ] @
| c#.NET
Pitanje, hocu da posaljem referencu (npr objekta RichTextBoxa) nekoj funkciji i da ta funkcija izvrsi upis u RTB, kako?
Sta treba da pise u deklaraciji funkcije i kako treba da je definisem...?
btw: Jel postoji u C# rad sa pokazivacima? Kako bi ovaj problem od gore uradio putem pokazivaca?
Hvala...! |
[ negyxo @ 17.09.2006. 23:51 ] @
Postoje pointeri u C# u okviru unsafe bloka ali za ovaj tvoj problem nema potrebe za tim. Ako bas hoces da prosledis bilo sta funkciji uvek mozes da stavis da ti je tip argumenta koji prosledjujes object. Konkretno za tvoj problem stavi da ti je tip argumenta RichTextBox i moci ces samo da prosledjujes objekte klase RichTextBox-a.
Code:
void SomeMethod(RichTextBox rtBox)
Pogledaj i starije teme o tipovima podatka. Neki su vec lepo opisali kako se objekti alociraju i prosledjuju.
[ Zevs85 @ 18.09.2006. 00:35 ] @
Plasim se da me nisi razumeo...
Ja hocu da izvrsim upis u RichTextBox, npr
Code:
void SomeMethod([b]RichTextBox rtBox[/b]){
rtBox.text = "neki tekst";
.
.
rtBox.text = "n-ti tekst";
}
To pozivem iz glavnog programa koji na sebi ima RTB i u njemu zelim upis.
Napomena: Ovaj bold tekst me konkretno zanima. Sta treba da napisem da bi radilo?
Citat: negyxo:
Pogledaj i starije teme o tipovima podatka. Neki su vec lepo opisali kako se objekti alociraju i prosledjuju.
Ne mogu da nadjem....
[ negyxo @ 18.09.2006. 01:08 ] @
I ja se plasim da te nisam razumeo, u stvari plasim se da te i dalje nisam razumeo
Probaj prvo. A ako to nije to onda bojim se da zaista ne razumem.
Starija tema: http://www.elitesecurity.org/t172066-0#1118871
[ dusty @ 18.09.2006. 05:53 ] @
Da bi 'preneo' neki objekat po referenci u metodu koristi se kljucna rec ref. Naravno, po referenci mogu da se prenesu samo referencijalni tipovi, u protivnom moras da radis boxing.
Code:
public void MyMethod(ref RichTextBox rtb){..........}
.
.
.
this.MyMethod(ref myRichBox);
.
.
.
Slicno se ponasa i out, stim da objekat ne mora da bude instanciran pre poziva metode, vec se pravi nova instanca unutar metode.
[ negyxo @ 18.09.2006. 09:35 ] @
Citat: dusty: Da bi 'preneo' neki objekat po referenci u metodu koristi se kljucna rec ref. Naravno, po referenci mogu da se prenesu samo referencijalni tipovi, u protivnom moras da radis boxing.
Referencijalni tipovi vec se prosledjuju preko reference. Koristiti ref za referencijalne tipove ima smisla jedino ako ce funkcija da koristi new operator nad tim argumentom. Sa ovim treba biti obazriv. Recimo, u ovom Zevs85-om problemu koristiti new operator unutar funkcije za RichTextBox koji je vec inicijalizovan i verovatno vec u nekoj controls kolekciji, moze dovesti samo do kreiranja novog RichTextBox-a koji nece referencirati onom u controls kolekciji.
ref je, koliko sam ja shvatio, najvise namenjen bas za value tipove. Boxing nema veze sad sa ovim. Boxing se radi - radi toga da bi objekat presao iz value tipa u object tip, recimo int se prevodi u object.
Citat:
negyxo: Ako bas hoces da prosledis bilo sta funkciji uvek mozes da stavis da ti je tip argumenta koji prosledjujes object.
Da ispravim sebe. Znaci stavljati da ti je tip object kojem ce se vrednost izmeniti unutar funkcije ima smisla samo nad reference types. Za value types koristiti ref ili out.
[ Dejan Vesic @ 18.09.2006. 09:55 ] @
Ovde je mnogo što šta pomešano :-S
- koristi ref kada izmenu radiš nad postojećim objektom (recimo kontrolom)
- koristi out kada šalješ referencu nad tek definisanim objektom
I to je to.
[ dusty @ 18.09.2006. 11:13 ] @
Da, pogresio sam za value type.
Citat: Referencijalni tipovi vec se prosledjuju preko reference
Da, ali se na stek ne stavlja referenca na objekat ako se ne koristi ref.
Citat: Koristiti ref za referencijalne tipove ima smisla jedino ako ce funkcija da koristi new operator nad tim argumentom
Ovo nema smisla  To je samo sintaksa. Ako se koristi new nekog tipa kao argument, JIT ce prvo da kreira objekat, pa ce da ga stavi na stek i pozove metodu. Samo ce da ti ustedi da ne moras da radis nekiObj obj = new nekiObj(); metoda(ref obj);.
[ negyxo @ 18.09.2006. 11:49 ] @
Citat:
Da, ali se na stek ne stavlja referenca na objekat ako se ne koristi /ref/.
To, znam. Zato sam i napisao da ima smisla koristiti jedino ako ce funkcija da koristi new operator nad tim argumentom
Code:
void SomeMethod(ref MyClass mc)
{
mc = new MyClass();
...
}
A pretostavljam da si ti mislio na ovo kod poziva funkcije
Code:
SomeMethod(ref new MyClass())
Sto ti nece ni proci jer ces dobiti compile time error.
[ mmix @ 18.09.2006. 11:57 ] @
Ajoj. "upucivac", gde si to pokupio?
Dalje, Nemo se ljutite, ali ja ne mogu da verujem koliko vas je zbunjeno oko ove veoma osnovne stvari.
1. Svi tipovi u .NETu su ili value ili reference (string je reference), ako niste sigurni koji je tip, verovatno je referentni
2. Svi reference tipovi se prosledjuju kao pointeri (type*). Tacka. .NET NIKAD nece napraviti kopiju objekta na steku pri formiranju stvarnih parametara (ali NIKAD), ni kao obican, ni kao ref ni kao out parametar.
3. Svi value tipovi se prosledjuju kopiranjem na stek sem kad su ref i out.
4. Ref parametar oznacava "pointer na". Posto je reference tip vec pointer, to znaci da se (ref TextBox x) prosledjuje kao pointer na pointer na objekat X (TextBox**). Jedini razlog da se ovo koristi je da bi promenila sama referenca u pozivnom kodu:
Code:
...
object x = new object();
PoRef(ref x);
// ovde x vise nije onaj koji je kreiran u konstruktoru
...
void PoRef(ref object x)
{
x = new object();
}
5. Ako hoces da menjas interno stanje objekta, ne treba da koristis ref parametre. Posto vec dobijas referencu po defaultu mozes da joj menjas interno stanje i ta promena ce ostati nakon povratka iz tela metoda.
6. ref na value type je dozvoljen i time se kompajler forsira da kreira pointer na value type. Proces je u pozadini isti kao proces boxovanja, ali je ovo "boxovanje" implicitno kao sto je i "unboxovanje" u telu funkcije implicitno, u prevodu potpuno transparentno. Iako radis sa pointerom na value type, sors kod je isti, kompajler je taj koji pravi razliku.
Znaci ref ne koristis kad radis izmenu NAD objektom, ref koristis kad radis ZAMENU objekta, out radis kad funkcija treba da vrati vise od jednog rezultata pa sam return value nije dovoljan. Princip out je isti kao princip za ref samo sto kompajler nece izbaciti warning ako stvarni parametar nije kreiran (pointer na null value je dozvoljen kao stvarni parametar).
[ Zevs85 @ 18.09.2006. 15:39 ] @
@mmix
Citat: Ajoj. "upucivac", gde si to pokupio?
Znas kako, tesko pitanje :), mislim da je jedna od Krausovih knjiga ili posledica nekih predavanja vezanih za objektno programiranje. Mada, sve u svemu, nazvao bi ih sinonimima, pa sam iz tog razloga naveo oba.
Citat: Dalje, Nemo se ljutite, ali ja ne mogu da verujem koliko vas je zbunjeno oko ove veoma osnovne stvari.
Ja sam u .NET-u, konkretno C# toliko svez da se jos dimim :) pre manje od mesec dana sam poceo. Radio sam c++, tako da sam se oko vecine stvari relativno lako uklopio, mada vidis ima problema sa osnovnim stvarima.
@All
Mnoge stvari su mi jasnije, VELIKO HVALA. Inace proradilo je ;)
[ Zevs85 @ 18.09.2006. 15:43 ] @
Ne znam da li da otvaram novu temu ili jednostavno da pitam ovde...
U c++u napraviti dinamicku listu (jednostruku) je bilo boza. Sintaksa koja je tamo palila ovde mi nesto ne prolazi (naravno sa izmenama). Gde bih mogao naci neki tutorijal ili osnovni primer, sta, kako...?
btw: Ima veze sa pokazivacima ;) bar je imalo u c++u
[ mmix @ 18.09.2006. 17:34 ] @
Citat: Zevs85: Ja sam u .NET-u, konkretno C# toliko svez da se jos dimim  pre manje od mesec dana sam poceo. Radio sam c++, tako da sam se oko vecine stvari relativno lako uklopio, mada vidis ima problema sa osnovnim stvarima.
To da si radio u C++-u se vidi iz aviona, i nisi prvi, ima nas dosta. C++ programerima treba dugo dugo da savladaju sve vestine vezane za pointere i cemu bi konkretno mogao da posluzi pointer na pointer na pointer  . Takodje, C++ ima monolitni kompajler koji (ako izuzmemo pragme) prevodi na osnovu sintakse i nije vezan za nijednu konkretnu biblioteku . C# (.NET generalno) su doneli tu promenu da kompajler ne zavisi samo od koda, nego i od toga koje se klase u kodu koriste (sto je varanje ako mene pitate  ). To je C++ programerima donelo najvise glavobolje, da alokacija, instanciranje i prosledjivanje razlicito radi za razlicitim tipovima bez eksplicitne instrukcije programera.
Citat: Zevs85: Ne znam da li da otvaram novu temu ili jednostavno da pitam ovde...
U c++u napraviti dinamicku listu (jednostruku) je bilo boza. Sintaksa koja je tamo palila ovde mi nesto ne prolazi (naravno sa izmenama). Gde bih mogao naci neki tutorijal ili osnovni primer, sta, kako...?
btw: Ima veze sa pokazivacima  bar je imalo u c++u
Ima jos uvek. Samo se opusti i zaboravi na * i ->  Kad deklarises sledeci clan niza, deklarisi ga kao polje, kompajler ce ga tretirati kao referencu (pointer):
Code:
public class Element
{
...
public Element Next;
}
Ako samo hoces da koristis uvezanu listu imas vec gotove implementacije u System.Collection i System.Collection.Generics
[ DarkMan @ 18.09.2006. 19:52 ] @
Citat: mmix:
1. Svi tipovi u .NETu su ili value ili reference (string je reference), ako niste sigurni koji je tip, verovatno je referentni :)
Nisam radio u c++ .NET (ili c++/cli) pa ne znam da li je tamo string value ili reference ali u c# string je value type. Da bi metoda mogla napraviti izmenu string parametra, taj parametar se explicitno mora proslediti sa ref.
[ Zevs85 @ 18.09.2006. 20:10 ] @
@mmix
Citat: C++ programerima treba dugo dugo da savladaju sve vestine vezane za pointere i cemu bi konkretno mogao da posluzi pointer na pointer na pointer .
Nadam se da se ovaj kontekst odnosi na c# ne na c++?! Obzirom da pricu oko pokazivaca i pokazivaca na pokazivac mi je kristalno jasna i istko tako jasno vidljiva u c++u. Ovde imam problem sto sam preskocio prvih par koraka, tacnije napravio sam dvokorak i bas se zbog toga gubim.
[ Dragi Tata @ 18.09.2006. 20:25 ] @
Citat: DarkMan: ali u c# string je value type
String je u svim .NET jezicima reference type. U stvari, to i nije definisano na nivou jezika, već na nivou CLRa.
[ mmix @ 18.09.2006. 21:14 ] @
Citat: DarkMan: Nisam radio u c++ .NET (ili c++/cli) pa ne znam da li je tamo string value ili reference ali u c# string je value type. Da bi metoda mogla napraviti izmenu string parametra, taj parametar se explicitno mora proslediti sa ref.
Kao sto ti rece DragiTata, nisi u pravu. Vecina ljudi se upeca na string, zato sam specijalno to i naglasio. Ono sto pravi problem je sto vecina string operacija zapravo pravi novi string na heap-u i onda vrati "referencu" u varijablu, i ta referenca se naravno ne vrati u pozivni kod i stice se utisak da je string value type jer se nije promenio. Ako npr. unutar metode promenis prvi karakter stringa sa "a" na "b" videces da ce se promena reflektovati u pozivnom kodu...
Code:
public void Met(string xx)
{
// ova promena ce se videti
xx[0] = "a";
// ova promena u xx ubacuje novu referencu (pointer) i ovo se ne vraca
xx = "aasafa";
// ovo takodje generise novu referencu
xx = xx.Replace("a", "x");
}
Citat: Zevs85:Nadam se da se ovaj kontekst odnosi na c# ne na c++?! Obzirom da pricu oko pokazivaca i pokazivaca na pokazivac mi je kristalno jasna i istko tako jasno vidljiva u c++u. Ovde imam problem sto sam preskocio prvih par koraka, tacnije napravio sam dvokorak i bas se zbog toga gubim.
Ako mislis na int***, mislio sam na C++ ;) Prosto i jednostavno, 3D matrica za sadomazohiste :) Ako to savladas, C++ pointeri su tvoji prijatelji :)
ja koliko znam, takva konstrukcija nije podrzana u CLR-u (postoje 3d matrice naravno, ali pointer na pointer na pointer, to ne :))
[ NrmMyth @ 18.09.2006. 21:34 ] @
Citat: mmix: Code: // ova promena ce se videti
xx[0] = "a";
Nije mi pri ruci C#, ni C++/CLI kompajler pa moram pitati.
Zar System::String nije immutable?
[ radoica @ 18.09.2006. 22:02 ] @
Immutable je.
A string is a sequential collection of Unicode characters that is used to represent text. A String object is a sequential collection of System.Char objects that represent a string. The value of the String object is the content of the sequential collection, and that value is immutable.
A String object is called immutable (read-only) because its value cannot be modified once it has been created. Methods that appear to modify a String object actually return a new String object that contains the modification. If it is necessary to modify the actual contents of a string-like object, use the System.Text.StringBuilder class.
[ mmix @ 19.09.2006. 12:12 ] @
Citat: NrmMyth: Nije mi pri ruci C#, ni C++/CLI kompajler pa moram pitati.
Zar System::String nije immutable?
Jeste, vidim da sam uneo jos vise zabune sad, izvinjavam se. Kod je samo trebao da pokaze da je string referentni tip i da kojim slucajem default indexer ima set :) promenio bi se string u pozivnom kodu...
[ NrmMyth @ 19.09.2006. 15:34 ] @
Bitno je naglasiti da pass-by-reference ustvari ne postoji.
[ mmix @ 19.09.2006. 20:46 ] @
Citat: NrmMyth: Bitno je naglasiti da pass-by-reference ustvari ne postoji.
Sad te ja nisam razumeo, kako mislis ne postoji?
Itekako postoji samo je implicitno, tu je glavni problem, moras da znas koje je vrste tip da bi znao da li je byref ili byval. Sintaksni oblik je identican, ali kompajler "vara" i na osnovu tipa odredjuje default pozivanje.
Ono sto ne postoji u .NET-u je u stvari pass-by-value referentnih tipova.
Code:
// pass-by-value za value type
C/C++ : void F1(int p)
C# : void F1(int p)
// pass-by-value za reference type
C/C++ : void F1(Klasa p)
C# : ne postoji
// pass-by-reference za value type
C/C++ : void F1(int* p)
C# : void F1(ref int p)
// pass-by-reference za reference type
C/C++ : void F1(Klasa* p)
C# : void F1(Klasa p)
// ovo ne znam ni kako bih nazvao tacno sem pointer na pointer :) :)
C/C++ : void F1(Klasa** p)
C# : void F1(ref Klasa p)
// jos jedna stvar koja ne postoji u .NETu
C/C++ : void F1(Klasa*** p)
kao sto se vidi, c/c++ kompajler pravi razliku izmedju byref i byval po sintaksi, .NET po tipu koji je koristi.
[ Dragi Tata @ 19.09.2006. 20:56 ] @
Ovo što je NrmMyth rekao važi za Javu: http://javadude.com/articles/passbyvalue.htm
Poenta je da kad pozivaš metod u Javi, ne prosleđuješ objekat po referenci, već referencu po vrednosti :)
Ali kod .NET-a možeš da proslediš parametre i po vrednosti i po referenci (ref keyword) http://www.yoda.arachsys.com/csharp/parameters.html
[ Zevs85 @ 19.09.2006. 23:55 ] @
Citat: mmix:
Code:
// pass-by-value za value type
C/C++ : void F1(int p)
C# : void F1(int p)
// pass-by-value za reference type
C/C++ : void F1(Klasa p)
C# : ne postoji
// pass-by-reference za value type
C/C++ : void F1(int* p)
C# : void F1(ref int p)
// pass-by-reference za reference type
C/C++ : void F1(Klasa* p)
C# : void F1(Klasa p)
// ovo ne znam ni kako bih nazvao tacno sem pointer na pointer :) :)
C/C++ : void F1(Klasa** p)
C# : void F1(ref Klasa p)
// jos jedna stvar koja ne postoji u .NETu
C/C++ : void F1(Klasa*** p)
kao sto se vidi, c/c++ kompajler pravi razliku izmedju byref i byval po sintaksi, .NET po tipu koji je koristi.
U c/c++
Code:
C/C++ : void F1(int* p)
pored prenosa objekta po referenci postoji i
Code:
C/C++ : void F1(int& p)
prenos reference objekta.
@Dragi Tata Na ovo si mislio?
[ NrmMyth @ 20.09.2006. 14:39 ] @
Izvinjavam se na konfuziji. :)
Mislio sam reci da kod pass-by-ref se dogodi pass-by-val pokazivaca, odnosno da se svaki pass-by-ref svodi na pass-by-val (njegovog pokazivaca).
Citat: mmix:
// pass-by-value za reference type
C/C++ : void F1(Klasa p)
C# : ne postoji[/code]
Dali to znaci da gornji izraz nece biti vidljiv van C++/CLI assemblya? Pretpostavljam da da.
[ mmix @ 20.09.2006. 16:02 ] @
Citat: NrmMyth:
Dali to znaci da gornji izraz nece biti vidljiv van C++/CLI assemblya? Pretpostavljam da da.
Nece se videti, bice prisutan u metadata, u npr. ovakvoj formi:
Code:
public int Test2(Class1 modreq(IsByValue) test)
C# i VB.NET kompajleri ne znaju kako da consume ovaj parametar i jednostavno ignorisu metod. Najgore je sto ni sam C++ ne moze da generise ovaj poziv, ne mozes cak ni da ga prevaris na jeftinu foru  :
Code:
public ref class Class1
{
public:
int Test2(Class1 test)
{
return 0;
}
int TestXXX()
{
return Test2(*this);
}
}
Dobijes bizarnu gresku (stvarno bi mogli da stave neku smisleniju):
cannot convert parameter 1 from 'Libcpp::Class1' to 'Libcpp::Class1'
Stari C++ (2003) mislim da cak nije ni dozvoljavao da bilo gde deklarises managed (__gc) klasu kao pass-by-value (requires toplevel *), cak iako si planirao da je zoves iz C++-a. Sad bar mozes da deklarises, ali ne vidim nacin kako bi mogao da je pozoves
Sve to ima smisla (inace bi to znacilo da CLR kreira shallow copy objekta na steku, i ode GC  )
Citat: Zevs85: U c/c++
Code:
C/C++ : void F1(int* p)
pored prenosa objekta po referenci postoji i
Code:
C/C++ : void F1(int& p)
prenos reference objekta.
F1(int* p) i F1(int& p) su gotovo identicni po pozadinskom funkcionisanju. Razlika je samo sto int& stiti prenesenu referencu (pointer) od promene (const int* p).
[ Zevs85 @ 22.09.2006. 14:43 ] @
@mmix
Citat: F1(int* p) i F1(int& p) su gotovo identicni po pozadinskom funkcionisanju. Razlika je samo sto int& stiti prenesenu referencu (pointer) od promene (const int* p).
Hoces da kazes da je isto (const int *p) i (int &p)? Nadam se da ne, posto to nije tacno...
Code: void f(int &p){ //ovo je ok
p=6;
}
void f(const int *p){ //ovo nece da valja, kompajler prijavljuje gresku
*p=6;
}
[ Dragi Tata @ 22.09.2006. 15:08 ] @
Citat: Zevs85: @mmix
Hoces da kazes da je isto (const int *p) i (int &p)? Nadam se da ne, posto to nije tacno...
Ne (const int* p), nego (int* const p) - lepote C-a, hehehe...
Inače, evo šta sam hteo da kažem. Uzimam C++ jer jedino on podržava sve varijante o kojima pričam:
Code:
void f(string a, string& b, string* c, string*& d);
Ovde je a string objekat i prenosi se po vrednosti, tj funkcija dobija kopiju objekta.
b je referenca na objekat i funkcija dobija kopiju reference koja pokazuje na isti objekat.
c je pointer na objekat i funkcija dobija kopiju pointera koja pokazuje na isti objekat. Ako unutar funkcije uradiš nešto blesavo kao što je c--, to će da se odrazi samo na kopiju pointera unutar funkcije.
d je referenca na pointer na objekat :) U ovom slučaju prosleđujemo funkciji pointer po referenci i ako napravimo d-- to će da izmeni i originalni pointer iz poziva.
E sad, pošto je ovo ipak .NET forum, u C#u bi to bilo nekako ovako:
Code:
struct NekiValueType {...}
class NekiRefType {...}
public void f(NekiValueType a, ref NekiValueType b, NekiRefType c, ref NekiRefType d){...}
Ovde je bitno istaći da d može da se promeni da pokazuje na drugi objekat i da to bude vidljivo iz koda koji je pozvao metod f, dok ako to uradiš sa c, promena je vidljiva samo lokalno u metodu f.
[ mmix @ 22.09.2006. 15:55 ] @
Citat: Zevs85: Hoces da kazes da je isto (const int *p) i (int &p)? Nadam se da ne, posto to nije tacno...
iskucano u brzini, sorry. Vidim da je dragi tata vec okacio ispravku, pa da ne ponavljam.
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|