Different ways of passing parameters to a .NET C# method.
This article is mainly about defining the ways of passing a parameter to a .NET C# method while calling it. In simple words, it is about the famous Ref and Val thing.
I know, I know. You might say:
This is a too basic thing that every .NET C# developer knows. Does it really need to be explained into a full article?!!!
The short answer to your question is: Yes. I know that it seems to be too basic as you said but I have my reasons.
In software, there are a lot of basic knowledge to go through and unfortunately, in the era of fancy frameworks and libraries, young developers tend to skip these basics and jump into learning these fancy frameworks.
Some of them might know about the basic rule, but they don’t know the story or the science behind it. Does it really matter? Yes, most of the times it matters.
Additionally, there is a kind of things that you need to thoroughly observe at least once, then you can live your life knowing that you did it. This topic is one of these.
Key Factors
There are two factors we need to keep in mind when trying to understand how a parameter is sent to a .NET C# method.
These factors are:
Parameter Type
Way of Passing Parameter
Therefore, it is now obvious that we would have 4 combinations:
Value By Value
Value By Reference
Reference By Value
Reference By Reference
How different types stored in memory?
As we said we have 2 types of parameters; Value and Reference. What you need to know is that these two types are not saved in memory in the same way.
In short, we have two types of memory:
▶ Stack
▶ Heap
Note: Explaining every tiny detail of the Stack and Heap is out of scope of this article. That’s why we would just summarize and focus on the small part we need for the main scope of this article.
The Stack
The Stack is where Value types are stored. Additionally, the addresses (Heap memory location) of Reference types (stored in the Heap) are stored in the Stack.
So, if we have:
int x = 1;
This would be stored in the Stack as follows.
The Heap
The Heap is where the Reference types are stored.
So if we have:
Employee x = new Employee();
This would be stored in the Stack as follows.
What does it mean passing a parameter by Value or Reference?
There is a golden rule here to keep in mind. It is simple and effective.
By Value
Means that at runtime, a copy of the original parameter -which is being passed to the method- would be passed to the method.
By Reference
Means that at runtime, the original parameter -which is being passed to the method- would be passed to the method.
Does it make any difference? For sure and that’s what we are going to discuss on the next sections of this article.
Having that said, let’s now analyze the different ways of passing parameters to a .NET C# method.
Value By Value
Let’s say that we have:
As you can see, the ValByVal method:
▶ Is expecting an int as an input parameter which is a Value type
▶ The parameter is expected to be sent by Value (there is no ref before the parameter type)
Therefore, it is guaranteed that the ValByVal method is a candidate for the Value By Value way.
So, back to the code, just after executing line 5, we would have this in the memory.
On line 7, when calling the ValByVal method, a copy of the variable x would be implicitly created and passed to the method. Let’s call this copy x’.
Therefore, on line 15 where we are incrementing the passed in parameter, we are actually incrementing x’, not x.
This would leave us with this:
This means that when we are back to the Main method on line 8, the value of the x would still be 1.
And the result on the console would be as follows:
Value By Reference
Let’s say that we have:
As you can see, the ValByRef method:
▶ Is expecting an int as an input parameter which is a Value type
▶ The parameter is expected to be sent by Reference (there is a ref before the parameter type)
Therefore, it is guaranteed that the ValByRef method is a candidate for the Value By Reference way.
So, back to the code, just after executing line 5, we would have this in the memory.
On line 7, when calling the ValByRef method, the original variable x would be passed to the method.
Therefore, on line 15 where we are incrementing the passed in parameter, we are actually incrementing x.
This would leave us with this:
This means that when we are back to the Main method on line 8, the value of the x would be 2.
And the result on the console would be as follows:
Reference By Value
Let’s say that we have:
As you can see, the RefByVal method:
▶ Is expecting an Employee as an input parameter which is a Reference type
▶ The parameter is expected to be sent by Value (there is no ref before the parameter type)
Therefore, it is guaranteed that the RefByVal method is a candidate for the Reference By Value way.
So, back to the code, just after executing line 10, we would have this in the memory.
On line 15, when calling the RefByVal method, a copy of the variable x would be implicitly created and passed to the method. Let’s call this copy x’.
However, what worth to mention here is that what is actually copied, is the value of x stored in the Stack. This value is the address of the memory location in the Heap where the actual Employee object is stored.
Thus, we would end up with this:
As you can see, x’ would hold the same address of the memory location in the Heap where the actual Employee X is stored. This means that x’ would also refer to the same exact object.
Therefore, on line 25 where we are updating the name of the employee to “Tarek”, we are actually updating the same object Employee ahmed which was originally passed to the RefByVal method.
Thus, this leads to this:
Then, on line 26 we are setting x’ itself to another new Employee. This means that a new Employee object would be created, stored in the Heap, and the address of that Heap memory location would be stored in x’ in the Stack.
Thus, this would leave us with this:
This means that when we are back to the Main method on line 17, the value of the name of the Employee ahmed would be Tarek.
And the result on the console would be as follows:
Reference By Reference
Let’s say that we have:
As you can see, the RefByRef method:
▶ Is expecting an Employee as an input parameter which is a Reference type
▶ The parameter is expected to be sent by Reference (there is a ref before the parameter type)
Therefore, it is guaranteed that the RefByRef method is a candidate for the Reference By Reference way.
So, back to the code, just after executing line 10, we would have this in the memory.
On line 15, when calling the RefByRef method, the original variable x would be passed to the method.
Thus, we would end up with this:
Therefore, on line 25 where we are updating the name of the employee to “Tarek”, we are actually updating the same object Employee ahmed which was originally passed to the RefByRef method.
Thus, this leads to this:
Then, on line 26 we are setting x’ itself to another new Employee. This means that a new Employee object would be created, stored in the Heap, and the address of that Heap memory location would be stored in x’ in the Stack.
But, x’ is actually x. This means that the address of x as well would be updated to the new address.
Thus, this would leave us with this:
This means that when we are back to the Main method on line 17, the value of the name of the Employee ahmed would be Hasan.
And the result on the console would be as follows:
Final Thoughts
I hope by now the story behind what is happening when calling a .NET C# method while passing in parameters is clear.
If you know someone who is starting his journey as a .NET C# developer, may be you can share with him this article. It would help him visualize what is actually happening.
Comments