Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ref - Parameters - Stack or Heap

Tags:

c#

Its only a theoretical question, but I can't get a good answer:

If I pass a parameter by ref, the object itself is passed and not a copy.

Here is what confuses me: As far as I know, each method has its own stack frame - memory, which they can't leave. So does that mean a ref - Object gets packed on the Heap and there is a reference to this parameter, or does the method go into the stack of the calling method and works there?

I'm sorry if my question is confusing, I basically would like to know how a ref type is saved and what impact it has.

Edith: I think I didnt make myself clear. I understand the concept of value and refence types. To make it easier, I try to explain it just by a value type, lets say Int:

Procedure 1 calls Prodecure 2 by passing an Int ByVal. This int has its own memory on the Stack of Prodecure 2, which means, altering this value in P2 doesnt change the Value in P1, since this 2 values are saved in each Stack once.

Now the same with byref: Prodecure 2 doesnt save a Copy of Int, but has access to this value directly. There are (in my Oppinion) two possibilies to make this work:

  1. The int gets packed on the Heap, and there are in fact 2 Pointers on this Int, but since its now on the Heap, the value changes are seen on both Prodecures.
  2. P2 has kindahow access to the Stack of P1, which I thought, is not possible, since this would mean, the Stack-lifetime is not setted in Stone.

Does this make it more clear what I mean?

like image 967
Matthias Müller Avatar asked Mar 12 '14 13:03

Matthias Müller


2 Answers

The parameter that is passed is an address to some object. That reference is passed on the stack, along with all other parameters to the method.

The actual object itself lives wherever it lived before you called the method. That could be in the stack, it could be in the heap, it doesn't matter. The act of passing an object by reference does not result in it being moved in memory, from say the stack to the heap, or from the heap to the stack.

like image 65
Servy Avatar answered Sep 21 '22 21:09

Servy


Although Servy has correctly answered the question, it seems there's an awful lot of confusion as to what the difference is between passing a parameter with ref and passing the reference of the object by value. For that reason, I think it's worth providing a short illustration.

Assume the following simple class:

class Player
{
    public Player(int health)
    {
        Health = health;
    }
    public int Health { get; set; }
}

We can now test updating the properties of the object and also changing the reference itself:

static void Main(string[] args)
{
    Player player = new Player(100);
    Console.WriteLine(player.Health);

    ChangeHealth(player);
    Console.WriteLine(player.Health);
    ChangeHealthByRef(ref player);
    Console.WriteLine(player.Health);

    ChangePlayer(player);
    Console.WriteLine(player.Health);
    ChangePlayerByRef(ref player);
    Console.WriteLine(player.Health);
}

static void ChangeHealth(Player player)
{
    player.Health = 80;
}

static void ChangeHealthByRef(ref Player player)
{
    player.Health = 60;
}

static void ChangePlayer(Player player)
{
    player = new Player(40);
}

static void ChangePlayerByRef(ref Player player)
{
    player = new Player(20);
}

Output:

100
80
60
60
20

ChangeHealth successfully modifies the Health property of the player object. ChangeHealthByRef also successfully modifies the Health property of the player object. So you can see, in both calls, the object to which player refers, can be modified, in spite of ChangeHealth using a copy of the reference.

Now, here's the part where I think people are getting confused:

ChangePlayer creates a new Player object which modifies the copy of the reference passed in. That means the change does not reflect in the calling code (i.e. Health still = 60). ChangePlayerByRef also creates a new Player object but, this time, it's modifying the reference directly, which means the change does reflect in the calling code (i.e. Health = 20).

like image 39
John H Avatar answered Sep 23 '22 21:09

John H