June 15, 2012

.NET Parameter passing


Recently, I had a dispute with co-worker about .NET passing parameter. So, I decide to write post about it and clarify some aspects. This post will show you how parameter passing is handled in memory.
Also this post expects that readers knew what's the difference between a value-type and a reference-type in .NET. By the way, I'm going to dive deeper into this question. Thus, wait for another post :)

In .NET we may passing parameter by value or by reference.
I break out a post into four parts :
  • Passing value-type variables by value;
  • Passing value-type variables by reference;
  • Passing reference-type by value;
  • Passing reference-type by reference.

Passing value-type variables by value

In this case, you are passing parameter in general way without any additional keywords.


static void Main(string[] args)
{
 int parameter = 10;
 DoSomething(parameter);
 Console.WriteLine(parameter); // 10
}

static void DoSomething(int x)
{
 x = 5;
}

After calling DoSomething parameter equals 10.
Look at image :

From method Main I'm calling method DoSomething and passing parameter variable as argument. In .NET local variables are placed on the stack. So, you can see that after calling DoSomething method, in stack allocated a new place for x variable and its value is coping from parameter variable.Thus, if I changed value of x variable into DoSomething method, it doesn't  affect parameter variable.

Passing value-type variables by reference

If you want to pass variables by reference you must use a special C# keyword - ref.
Let's change previous example :

static void Main(string[] args)
{
 int parameter = 10;
 DoSomething(ref parameter);
 Console.WriteLine(parameter); // 5
}

static void DoSomething(ref int x)
{
 x = 5;
}

I added keyword ref to DoSomething's signature and before passing parameter variable.
Let's see whats going on the stack (look at image on the right).

On the top of the stack you can see x : POINTER.
POINTER is basically as GOTO instruction.
So now, if you change the value of x you also change the value of parameter variable.

That's why on console window you see 5 (not 10).


Passing reference-type variables by value

Passing reference-type by value is similar to passing value-type by reference.
For example, you have classes such as:
class Human
{
 public int Age { get; set; }
}

class Boy : Human
{
}

class Girl : Human
{
}

And now, you want to execute something like this :
static void Main(string[] args)
{
 Human human = new Boy { Age = 10 };

 DoSomething(human);

 Console.WriteLine(human.Age); // 5
}

static void DoSomething(Human x)
{
 x.Age = 5;
}

Take a look at image on the right. Here what's happens:
  1. Starting with the Main method the variables human goes on the stack.
  2. Starting with the call to DoSomething() the argument x goes on th stack.
  3. The value of human (the address of Boy on the stack) is copied to x.
So it makes sense that when we change Age property of Boy object on the heap using x variable(DoSomething method) and later refer to the object on the heap using human variable, we get the value of Age equals 5.

Passing reference-type variables by reference

And the last approach that you can use to pass parameters between methods.
For example, you want to execute this:

static void Main(string[] args)
{
 Human human = new Boy();

 DoSomething(ref human);

 Console.WriteLine("human is Boy : " + (human is Boy).ToString());
 Console.WriteLine("human is Girl : " + (human is Girl).ToString());
}

static void DoSomething(ref Human x)
{
 x = new Girl();
}

On the console window you'll see :
human is Boy : False
human is Girl : True
Let's take a look at what's happening:

  1. Starting with Main method the human pointer goes on the stack;
  2. The Boy goes on the heap;
  3. Starting with DoSomething method the x goes on the stack and points to human;
  4. The Girl goes on the heap;
  5. The value of human is changed through x to the address of the Girl.
If you don't pass Human by ref you'll get the opposite results from this code...

No comments:

Post a Comment