Passing Parameters in C#
I am writing this post as complementary to the following post where I explained some of the C# Memory Management concepts such as Value and Reference Types.
In this post, I will write about how to pass parameters to the functions in C#. I will give code examples and outputs (including both value types and reference types).
First, let’s define value type and reference type:
A value type variable contains its data directly whereas a reference type variable contains a reference to its data.
In C#, arguments can be passed to parameters either by value or by reference.
Before moving forward, I want to make clear what we mean by parameter and argument:
Let’s start with how to pass parameters by value.
Passing By Value
By default, parameters are passed by value in C#. When arguments are passed to parameters by value, a new storage location is created for the parameter variable and the value of the argument variable is copied to this location.
Now, let’s examine how value and reference types are passed by value.
Value Type
If you copy a value type variable to another variable, the value is copied directly. Then both variables work independently.
Let’s see this in an example:
Output:
Reference Type
If you copy a reference type variable to another, as reference type variables represent the address of the variable, the reference is copied and both variables point to the same location of the heap.
Output:
As both parameter variable ( person
) and argument variable ( alice
) point to the same location after the copy, the change made in the function became permanent after the function call.
Passing By Reference
When arguments are passed to parameters by reference, rather than creating a new storage location for the parameter variable, the same storage location is used with the argument variable, so the value of argument and parameter variable will always be the same.
Parameters are passed by reference using ref
, out
and in
keywords.
Let’s start with ref
keyword.
ref Keyword
ref
keyword is used to pass a parameter by reference for input and output.
An argument that is passed to a ref
parameter must be initialized before it is passed.
We should use the ref
modifier before both parameter and argument variable.
I will use the same examples that I used in the Passing By Value part so that you can see the difference in the outputs.
Value Type
Output:
As you see, value change is still valid even after the function is executed.
Reference Type
Output:
The output is the same as in the Passing By Value example, so what’s the difference between them really? Let me explain:
If you noticed, there is a line in the former one as below:
I did not add this line in the latter one deliberately in order to show the difference between these. Now, let’s insert that line to our current example (with an extra if
control) and see the output:
Output:
As person
and alice
variables share the same location, when we set person
to null, alice
variable lost the connection to the object on the heap, so we cannot access Alice’s age any more.
I hope everything is clear in your mind up to this point. If you want to see topics covered until now with a visual representation, I recommend you read this article.
out Keyword
out
keyword is used to pass a parameter by reference for output. It means we cannot pass a variable value as input using out
parameter.
Variables passed as out
arguments do not have to be initialized before being passed in a method call. Even if it is initialized, this value cannot be accessed inside the method.
The called method is required to assign a value to out
argument before the method returns.
out
modifier must be used before both parameter and argument variable.
Now, let’s see all of these in an example:
Output:
One of the new features came with C# 7.0 is inline out
variable declaration. We can write the above code as below:
in Keyword
This feature came with C# 7.2.
in
keyword is used to pass a parameter by reference for input. in
arguments cannot be modified by the called method.
Variables passed as in
arguments must be initialized before being passed in a method call.
in
modifier is optional at the method call. It is only required in the method declaration.
Now, let’s see all of these in an example:
Output:
Now, you can ask the question that why we need in
parameters. Below is the answer from Microsoft C# documentation:
Defining methods using
in
parameters is a potential performance optimization. Somestruct
type arguments may be large in size, and when methods are called in tight loops or critical code paths, the cost of copying those structures is critical. Methods declarein
parameters to specify that arguments may be passed by reference safely because the called method does not modify the state of that argument. Passing those arguments by reference avoids the (potentially) expensive copy.
Lastly, I want to mention limitations about using ref
, out
and in
modifiers:
- Methods cannot be overloaded if the only difference is that one method takes a
ref
orin
argument and the other takes anout
argument. The following code will not compile:
2. in
, ref
, and out
keywords cannot be used for the following kinds of methods:
- Async methods, which defined by using the
async
modifier. - Iterator methods, which include a
yield return
oryield break
statement.
I hope you found this post helpful and easy to understand. Please let me know if you have any corrections and/or questions.
Bye C#ers :)
References
https://docs.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/ref
https://docs.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/out-parameter-modifier
https://docs.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/in-parameter-modifier
http://jonskeet.uk/csharp/parameters.html#ref
https://www.c-sharpcorner.com/article/understanding-ref-and-out-with-c-sharp-7/