02. november 2005 - 07:52Der er
23 kommentarer og 2 løsninger
C#, pointers, clonings m.m.
Oplevede en interessant problematik da jeg sad og arbejdede på et større projekt med en masse ref's og andet sjov i aftes... Jeg ved godt at egentlige pointers i C# er noget unsafe fybæ, men hvordan så?
Hvornår "kloner" C# et object og hvornår laver den en pointer til et objekt?
Der er forskellige problemstillinger jeg er bekendt med, f.eks.
private void test(Socket testSocket) { // testSocket er en klon af socket parses til funktionen, med mindre ref bruges.. }
Men problemet er, og mit egentlige spørsmål er, hvornår klones objekter og hvornår oprettes der pointere til samme..
F.eks. hvis jeg selv har lavet et objekt ud fra en klasse:
TestClass classA = new TestClass(); TestClass classB;
classB = classA;
Alle ændringer jeg foretager med classA bliver også reflekteret i classB - er det pga. reflection eller fordi B bare er en pointer til A - oder was?
Envidere når jeg forsøger det samme med:
string A = "testA"; // eller String A; string B = "testB"; // eller String B;
Så er der ingen reflektion, og disse operere hver for sig?
I C# (og de fleste andre sprog) skelnes mellem en value type og en reference type. En value type bliver altid sendt med til metoder som værdi (dvs. den bliver kopieret), mens en reference type bliver sendt med som en reference (dvs. du peger på et eksisterende objekt).
Som standard er alle simple typer (dvs. dem der kan bruges uden initialisering med new) value types. (Teknisk set er string ikke simpel, men den tager vi en anden dag.) Klasser er reference types.
Der er dog den undtagelse, der hedder en struct - i C# er der ingen forskel på en struct og en class, bortset fra at en struct altid er en value type. Dvs. at du kan sikre dig at dine objekter kopieres hvis du ændrer dem fra classes til structs.
Lækkert - jeg har nemlig haft nogle dilemma'er med at rette noget kode efter for andre, hvor netop brug og "kopiering" af sockets har været problematisk.. Men nu er alt gjort lidt klarer :)
bemærk at de slags typer: value typer = typer hvor variabel har værdien reference typer = typer hvor variablen peger på noget og argumenter i kald: ingenting = by value angivelse af ref = by reference er uafhængige af hinanden.
Ah, okai - men i ovenstående eksempel vil ændringer foretaget i socketen, i funktionen, vil afspejles uden for funktionen (indtil jeg overskriver socketen i funktionen med en ny instans)?
Man kan ikke overføre en reference type over by value. Jeg synes at kalde det at overføre en reference type by value er forkert. hvis du bruger ref på en referencetype får du en reference til en reference, det er således muligt at skifte en streng ud.
du har: value typer by value (f.eks. int uden ref) value typer by reference (f.eks. int med ref) reference typer by value (f.eks. string uden ref) reference typer by reference (f.eks. string med ref)
svarende til C++:
int int& int* int*&
og bloggen er forkert - termerne by value og by reference har helt præcise veldefinerede betydninger som er ældre end både .NET og Java - det hedder by value og by reference
det ændrer ikke på at by value i .Net betyder værdien af variablen som er en reference. Det giver sgu da ingen mening... I Java dokumentation står der at reference typer bliver overført by reference, og det er det samme der sker.
Når jeg bruger ordet by value, forventer jeg at indholdet af mit objekt bliver kopieret... det gør det ikke
med en reference forstår jeg det der svarer til en pointer, bare uden selv at kunne sætte den. ref på objekter i .Net svarer til det jeg kender som pointer til en pointer i C++.
hvis der i java dokumentationen står at "reference typer bliver overført by reference", så er det en fejl - java kan kun overføre by value - det kan du finde udførligt beskrevet masser af steder - har du et link til den dokumentation du henviser til ?
og man kan ikke ændre på betydningen af termer som "by value" og "by reference" der har eksisteret i 30-40 år
man kan muligvis klandre både .NET og Java for at have valgt den lidt kryptiske "reference typer" som godt kan give de forkerte associationer
ikke mindst fordi en reference type by value gør det som mange tror at by reference drejer sig om - og jeg har sikkert også selv udtalt "java sender ikke-simple typer over by reference"
----
C int** svarer stort set til C++ int*&, men jeg synes at den sidste mere præcist beskriver hvad man vil (int** kan også bruges i andre sammenhænge som f.eks. et 2D jigsaw array)
Java overfører objecter som reference og simple typer som værdier. Alle jeg kender der har læst om det har forstået disse koncepter med det samme. Java certificeringerne går meget op i dette.
.net overfører simple typer som værdier og objecter som referencer(ligesom Java). Derudover kan man vælge at ville overføre "by reference" som for simple typer betyder en reference, og som for objecter betyder en reference til den reference man havde i forvejen.
Vi er enige om hvad der sker. Det eneste jeg ikke kan lide er .net's dokumentation, altså at når man overfører et object "by value", så får man overført en reference. Jeg har mødt personer der overfører parametre byref for at performance optimere sin kode...
og jeg vil stadigvæk gerne have et link til "I Java dokumentation står der at reference typer bliver overført by reference"
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.