In C#, when defining a Method with Parameters, you can tell the compiler about how you would like to access these said parameters, i.e
- do you just want to create a copy of the passed arguments or
- do you just want the memory address of the passed argument or
- whether you only want read access to the data stored within the passed argument or
- do you want both read and write access to the data or
- maybe do you only want write access to the passed argument
Knowing how you are accessing the passed arguments for the defined parameters of a method is really important
and to do this in C#, we use the in, ref and out Keywords.
Now, if you don’t know anything about methods, then i suggest that you start from the first article
I’ve divided my explanation of Methods in 4 different articles as otherwise the articles would be too long.
List Of All Articles To Master Methods In C#
- Part 1 – Basics Of Methods
- Part 2 – Multiple, Required and Optional Parameter + Named Arguments
- Part 3 – Overload Resolution
- Part 4 – In, Out and Ref Keywords <— Currently You Are Here! :p
In this article, I’ll will be talking about in, ref and out Keywords and will be covering
- The concept of Passing Arguments By Value and By Reference and the Difference between these two approaches.
- Then we will go over the in, ref and out Keywords and understand what they are and the differences between them.
- While going over them, we will also code and see how to use the in, ref and out keywords in your C# scrpits in Unity.
So, without further ado, let’s dive directly into it!
This Post is Part of : How To Make A Game Series where I’ll be showing you how to become a game developer and will be going over the basics of Game Development, Step by Step, using the Unity Game Engine and C# Scripting Language to script the Game Logic.
If you are new to Game Development or Programming in general you should definitely go through this Unity Tutorials article series as it will set give you a kick-start towards becoming an exceptional Unity 2D or 3D Video Game Developer.
Game Development is one of those professions that needs a couple of different professions to work in conjunction to be done right.
If you are someone completely new to Game Development and don’t know much about it,
then you might be interested in the these articles on Intro To Game Development and Game Development Softwares (Game Engines, 2D Art, 3D Art, Code Editor, DAW)
in which i have talked about the Art of Game Development, Various Roles in Game Dev, Softwares you will need based on the different categories of Game Development
and about the Recipe of Success that will help you in having the right mindset as you get into Game Dev.
What we have Covered So Far About Methods inn C#
In the last three articles we have talked about
- What methods are and how we can define a method
- How you can create methods with Multiple, Required and Optional Parameters and pass arguments using Named Arguments
- and lastly we also talked about the topic of Method Overloading
Now, i know that all these technical stuff can be really boring
but i want to make sure that i tell you about the major differences between these concepts
so that you have strong fundamentals
which will stop you from making mistakes that will make you redo a huge part of your code.
and maybe even if you made those mistakes in the future because you know everyone’s human
at least you would understand why your game is behaving the way it is, if you know these concepts.
So beware, this is going to get a bit technical :p
Passing Arguments By Value Or By Reference | Unity C# Game Development Tutorial
let’s move forward and talk about the concept of Passing Arguments by Value or by Reference.
Now, without going into too much detail,
when you pass an argument by Value
what you are doing is, you are making a copy of the variable or value that you passed in as the argument.
This is what we have been doing so far.
while when you pass an argument by Reference
instead of making a new copy,
you are pointing towards the memory location where the data of the passed argument is stored.
Now, by default any argument that you pass in the method call will be by value even if the variable is a Reference Type.
When you pass arguments by value
any operations that you do on the copy of the passed argument
will not affect the data inside the variable that you passed as the argument.
They are two completely different set of data,
so don’t confuse that.
Now when you pass by reference
you only have a single copy of data
that is being referenced by n number of variables.
So, if a change is made to this single copy of data through any one of the variables
this change in data, like a domino effect
will be seen in all the variables
Difference Between Value Types Or Reference Types And Passing Arguments By Value Or By Reference in C#
There is another concept in C# and that is the concept of Value Types and Reference Types
Now with the wordings being so similar
i.e. The Concept of Passing by Value or by Reference
and The Concept of Value Types or Reference Types
it is not weird that so many people start getting confused
and start mixing these two completely different concepts with each other
so let me stop you from doing that before you even start
When you see any place that’s talking about Value Types and Reference types
what they are talking about are the main categories that the Types in C# are divided into
while when you see any place talking about Passing by Value or Passing by Reference
they are talking about, how the arguments are being passed in a method call.
A lot of beginners have a misconception that
Reference Types when used as arguments are by default Passed by Reference, which is not true
as i have said before, everything that you pass in an argument by default is by Value
We can go into more detail about Value Types and Reference Types
and talk about how all that works but i think it will be relatively complex for beginners
so let’s talk about that in another article series.
in Keyword | Unity C# Game Development Tutorial
Now moving forward, as i said in the introduction
In C#, to pass an argument by Reference,
we can use the in, ref or out Keywords
Now let’s look at this 3 keywords one by one
When you use the in keyword to pass the argument
this passed argument will be Read-Only
and you will not be able to modify it’s content inside the method’s code block.
To show this, let’s first declare a method named modifyEnemies
and define an int parameter named numberOfEnemies in it, with the in keyword before it
Now let’s try to modify this variable inside the method’s code block, like this
// Everything below is inside a Class.
private void modifyEnemies(in int numberOfEnemies)
{
numberOfEnemies = 5;
}
As you can see in the image above, we get a Compile Time Error as shown by the Red Underline
and this is because we are trying to modify a Read Only variable.
So, let’s remove it.
Next, when you want to use the in keyword to pass an argument,
the Variable or Value that is being passed as argument
has to be declared and initialized before the method call.
So, let’s initialize a variable named enemyCount and set it to 10
and log it’s value in the Unity Console, like this
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
}
private void modifyEnemies(in int numberOfEnemies)
{
}
Unlike ref and out keywords when using the in keyword
you can choose to not explicitly type the in keyword before the passed argument in the method call
But i would suggest that you don’t do this.
As explicitly typing the in keyword will make your code much more readable
and also make sure that you know what type of argument you are sending,
just by looking at your method call without having to go and look at the method definition
So, now let’s make the method call with the enemyCount variable as argument using the in keyword
and inside the method’s code block, log it’s value like this.
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(in enemyCount);
}
private void modifyEnemies(in int numberOfEnemies)
{
Debug.Log("Number Of Enemies: " + numberOfEnemies);
}
With this we would be able to see if the argument is being passed correctly or not
Now let’s go to unity and check the logs.
Unity Log | in keyword | Unity C# Game Development Tutorial
As you can see both the logs show the same value
which means everything is working correctly.
ref keyword | Unity C# Game Development Tutorial
Back to the code, now let’s move forward to the ref keyword.
The ref keyword will let you read and modify the value of the argument
that you have passed by Reference inside the method call
just like the in keyword the argument that is to be passed
needs to be declared and initialized before the method call.
unlike the in keyword, it is mandatory to explicitly type ref in both the places
i.e. Before the Parameter in the Method Definition and also Before the Argument in the Method Call
So let’s modify the code we wrote previously and change the in keyword to ref as shown below
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(ref enemyCount);
}
private void modifyEnemies(ref int numberOfEnemies)
{
Debug.Log("Number Of Enemies: " + numberOfEnemies);
}
also let’s suppose that the argument you are passing i.e. enemyCount is Referencing Memory Location x of your memory.
Now this memory location stores an integer value 10.
So when we are using the ref keyword,
if we make any changes to numberOfEnemies
we won’t see any errors
like what we saw with the in keyword
and this change that we did, will be done to Memory Location x
as the numberOfEnemies parameter is referencing that memory location
just like the enemyCount variable that we passed as argument.
So, if we were passing by value instead
numberOfEnemies and enemyCount variables would not be referencing the same memory location
and there would be 2 copies of the integer with value 10 in our memory at different memory locations
with each of these variables referencing one of these memory location
but by using the ref keyword,
we are not making another copy and both the variables are referencing the same memory location
Now let’s modify numberOfEnemies like this.
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(ref enemyCount);
}
private void modifyEnemies(ref int numberOfEnemies)
{
Debug.Log("Number Of Enemies: " + numberOfEnemies);
numberOfEnemies = 5;
}
When we modify the value of numberOfEnemies in the method’s code block
any other variable that is also referencing memory location x
will also have their values changed
as all these variables including enemyCount and numberofEnemies variables are all referencing a single copy of data that is located at memory location x
and you just changed that single copy of data.
Now, let’s write some Debug.Logs that will show you that
we are truly referencing the same copy of data in both these variables.
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(ref enemyCount);
Debug.Log("Modified Enemy Count: " + enemyCount);
}
private void modifyEnemies(ref int numberOfEnemies)
{
Debug.Log("Number Of Enemies: " + numberOfEnemies);
numberOfEnemies = 5;
Debug.Log("Modified Number Of Enemies: " + numberOfEnemies);
}
Now let’s execute this piece of code in Unity and check the logs
Unity Log | ref keyword | Unity C# Game Development Tutorial
As you can see in the image above,
the first log in which we are logging enemyCount’s default value shows 10
then the second log inside the method’s code block where we are logging numberOfEnemies show 10
then the third log is after we modified numberOfEnemies and it show 5
and then we have the fourth log in which we are logging enemyCount variable after the method call and it is also showing 5.
This clearly shows that both these variables are referencing the same memory location
because if they did not then enemyCount would still be 10 in the fourth log.
out keyword | Unity C# Game Development Tutorial
Now let’s move forward to the out keyword.
A normal method uses the return keyword to send back a value or variable of the defined return type to the line from which we called the said method.
But the limitation here is that, you can only send back a single value or variable.
The out keyword can be used when you want to return more than one value or variable from the method.
what you need to know is that, the out keyword only allows you to set a value to the passed argument.
Before setting the value to this passed argument inside the method’s code block
you won’t be able to read the data inside the passed argument.
to show this In the Start Method
let’s modify the method call again and change the ref keyword to out
and then in the method definition do the same
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(out enemyCount);
Debug.Log("Modified Enemy Count: " + enemyCount);
}
private void modifyEnemies(out int numberOfEnemies)
{
Debug.Log("Number Of Enemies: " + numberOfEnemies);
numberOfEnemies = 5;
Debug.Log("Modified Number Of Enemies: " + numberOfEnemies);
}
and as you can see in the image above,
if we try to do this we will get a Compile Time Error in the first log
but we don’t get this error in the second log
because the second Debug.Log is done after setting the value for the out parameter i.e. numberOfEnemies.
So let’s remove the first log.
// Everything below is inside a Class.
void Start()
{
int enemyCount = 10;
Debug.Log("Enemy Count: " + enemyCount);
modifyEnemies(out enemyCount);
Debug.Log("Modified Enemy Count: " + enemyCount);
}
private void modifyEnemies(out int numberOfEnemies)
{
numberOfEnemies = 5;
Debug.Log("Modified Number Of Enemies: " + numberOfEnemies);
}
Next, when we are using the out keyword
it is okay to not initialize the argument’s value.
so to test that let’s remove the initialization of 10 from enemyCount and remove the log below it
like this.
// Everything below is inside a Class.
void Start()
{
int enemyCount;
modifyEnemies(out enemyCount);
Debug.Log("Modified Enemy Count: " + enemyCount);
}
private void modifyEnemies(out int numberOfEnemies)
{
numberOfEnemies = 5;
Debug.Log("Modified Number Of Enemies: " + numberOfEnemies);
}
and as you can see in the image above, we didn’t get any compile time errors
So until now, what we have done is
we have declared enemyCount variable but we did not initialize it.
Then we used it as the out parameter when calling the method.
Now when the method’s code block is executed
it will set value to numberOfEnemy out parameters
And as numberOfEnemy parameter is actually being passed reference of enemyCount variable
that is not local to the method
the values inside enemyCount variable will persist even after we leave this method.
Hence allowing us to return more than one value or variable, if we declare more than one out parameter.
With that done, another thing is that
you need to assign values to all the out parameters before leaving the method
otherwise you will get a compile time error, saying that
“out parameter x needs to be assigned before control leaves the current method.”
Now, let’s go to unity and check the logs.
Unity Log | out keyword | Unity C# Game Development Tutorial
As you can see the both the logs show value of 5
which means that the out keyword is working as intended.
Limitations When Using in, ref and Out keywords | Unity C# Game Development Tutorial
Now there are Limitations on how you can use these 3 keywords.
First is that, you can’t use them in Async methods,
which you define by using the async modifier.
Second, you can’t use them in Iterator methods,
which include a yield return or yield break statement.
and Third, there are some limitations regarding their use in extension method
but for now skip that as extension method is not a beginner concept.
Now, i know that this would not make much sense right now as i have not covered these topics yet
but i wanted to pass this information here so you at least know that these limitations do exist
when it comes to in, ref and out keywords.
With that i think i have covered everything that can be considered as beginner level in respect to methods
and we can finally move on to other topics from the next article.
List Of All Articles To Master Methods In C#
- Part 1 – Basics Of Methods
- Part 2 – Multiple, Required and Optional Parameter + Named Arguments
- Part 3 – Overload Resolution
- Part 4 – In, Out and Ref Keywords <— Currently You Are Here! :p
Conclusion
Well folks, that does it for this article.
i hope that this information will be helpful to you.
Share this post and follow us on Social Media platforms if you think our content is great, so that you never lose the source of something you love.
If you like the content do go through the various articles in How To Make A Game Series that this post is a part of and also go through the other series we have on Bite Sized Tech.
Also we have a YouTube Channel : Bite Sized Tech where we upload Informational Videos and Tutorials like this regularly. So, if you are interested do subscribe and go through our Uploads and Playlists.
Follow Us On Social Media
Goodbye for now,
This is your host VP
Signing off.
Articles In How To Make A Game Series
Game Development Softwares (Game Engines, 2D Art, 3D Art, Code Editor, DAW)
Methods | Part 1 – Basics of Methods
Methods | Part 2 – Multiple, Required & Optional Parameters + Named Arguments
Methods | Part 3 – Overload Resolution
Methods | Part 4 – In, Ref and Out Keywords