[ALG] Object References

Pagina: 1
Acties:

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik had voor mijn gevoel redelijk duidelijk hoe het met references zit maar ik loop toch tegen iets aan.

Als ik een variabele heb gedefinieerd op niveau x en ik wijzig de variabele op niveau y dan krijg ik op niveau x de wijziging weer te zien. Perfect want dit is ook precies wat ik wil. Alleen wanneer ik op niveau x de variabele aanmaak en een nieuwe instantie op niveau y er over heen zet, dan krijg ik deze nieuwe instantie niet op niveau x te zien. Ik begrijp niet goed waarom omdat ik dacht dat de waarde van de reference gewoon overschreven werd, maar het lijkt wel dat hij op niveau y een gehele nieuwe geheugen locatie krijgt toegewezen.

Ik heb onderstaande test aangemaakt om het één en ander te verduidelijken. Iemand enig idee waar mijn gedachten verkeerd gaan?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Collections.Generic;
using System.Text;

namespace ReferenceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Candidate candidate = new Candidate(10);
            Console.WriteLine("CandidateID: " + candidate.ID);

            ReferenceTest test = new ReferenceTest(candidate);            
            test.ChangeCurrentInstanceCandidateID(15);
            Console.WriteLine("CandidateID: " + candidate.ID);

            test.ChangeNewInstanceCandidateID(20);
            Console.WriteLine("CandidateID: " + candidate.ID);

            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }
    }

    public class Candidate
    {
        private int id;

        public int ID
        {
            get { return id; }
            set { id = value; }
        }

        public Candidate(int id)
        {
            this.id = id;
        }
    }

    public class ReferenceTest
    {
        private Candidate candidate;

        public ReferenceTest(Candidate candidate)
        {
            this.candidate = candidate;
        }

        public void ChangeCurrentInstanceCandidateID(int id)
        {
            this.candidate.ID = id;
        }

        public void ChangeNewInstanceCandidateID(int id)
        {
            this.candidate = new Candidate(id);
        }
    }
}


Hier onder de output.

code:
1
2
3
4
CandidateID: 10
CandidateID: 15
CandidateID: 15
Press any key to quit


Ik zou verwachten dat de laatste regel "CandidateID: 20" zou worden.

PSN: Norfirin


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een variabele zelf is alleen een verwijzing naar een stuk geheugen. Zie het als een int, die in plaats van een getal een geheugenadres opslaat. Als je de ene int variabele toekent aan de andere int variabele, en je telt (bijv.) 10 bij die andere variabele op, dan verandert die eerste ook niet. Bij verwijzingen is dat net zo. Als je een nieuwe instance maakt en die toekent aan een variabele, dan wijzigt de verwijzing van die variabele, maar niet die van een andere.

Echter, de verschillende variabelen wijzen allemaal naar hetzelfde object. Dus als je een object aanpast, dan zie je dat vanzelfsprekend terug bij elke variabele die naar dat object wijst. Want in dat geval pas je dus het object zelf aan, en niet de variabele die de verwijzing naar dat object onthoudt.

Een voorbeeld:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyObject
{
    public int value = 1;
}

class Program
{
    public static void Main(string[] args)
    {
        int a = 1;    // #1
        int b = a;    // #2
        b += 10;      // #3

        MyObject o = new MyObject;  // #4
        MyObject p = o;    // #5
        p.value += 10;     // #6
        o = new MyObject;  // #7
    }
}

Het geheugen na iedere stap ziet er dan ongeveer zo uit:
code:
1
1     // int a

code:
1
2
1     // int a
1     // int b

code:
1
2
1     // int a
11    // int b

code:
1
2
3
4
5
6
7
8
9
1     // int a
11    // int b
@8    // MyObject o




// MyObject instance
1    // int value

code:
1
2
3
4
5
6
7
8
9
1     // int a
11    // int b
@8    // MyObject o
@8    // MyObject p



// MyObject instance
1    // int value

code:
1
2
3
4
5
6
7
8
9
1     // int a
11    // int b
@8    // MyObject o
@8    // MyObject p



// MyObject instance
11   // int value

code:
1
2
3
4
5
6
7
8
9
10
11
12
1     // int a
11    // int b
@11    // MyObject o
@8    // MyObject p



// MyObject instance
11   // int value

// MyObject instance
1    // int value

Je ziet, dat een expressie als new MyObject een stuk geheugen reserveert voor het object, en de verwijzing naar dat object teruggeeft. Die verwijzing ken je toe aan een variabele. Door de "." te gebruiken achter de variabele om de members van het object aan te spreken, volg je eigenlijk de verwijzing, dit noemt men 'dereferencing'. Vandaar dat het lijkt dat elke variabele die wijst naar hetzelfde object aanpast, maar eigenlijk is dat niet zo - de variabele blijft naar hetzelfde object wijzen, het is juist dat object zelf dat je aanpast.

En daarom zie je die aanpassing niet terug als je de variabele een andere verwijzing (een nieuwe instance) toekent. Zoals je in #7 ziet, verandert o door naar een nieuwe MyObject instance te wijzen, maar p wijst nog altijd naar de oude. p.value blijft dus 11, terwijl o.value nieuw is.

[ Voor 58% gewijzigd door .oisyn op 12-12-2008 15:29 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

+1 voor uitleg.

.oisyn, heb je er bezwaar tegen als ik jouw uitleg betreffende referenties gebruik in onze developers quickstart voor stagieres? Dan hoef ik niet meer mijn verhaal met de koektrommels en de koekjes te houden ;-)

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Prima :)

Geniale sig trouwens, kende ik nog niet :D

[ Voor 87% gewijzigd door .oisyn op 12-12-2008 15:34 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Thanks man! Ik denk dat ik het begrijp. Zal het de komende dagen nog een paar keer doornemen ;)

PSN: Norfirin