In C#, arguments can be passed to the parameters either
- by value, or
- by reference
Passing arguments by reference allows the changes made by the methods to be persisted at the calling site.
Pass by reference can be achieved by using the keyword ref
and out
, which we have covered in the topic “Functional side effects”
Do note that there are slight differences among
- passing value-type by value
- passing reference-type by value
- passing value-type by reference
- passing reference-type by reference
Value-type vs. reference-type
A value-type variable directly contains the data as compared to reference-type, which contains a reference (or pointer) to the data.
Value-types include:
- numeric types (
int
,long
,byte
,float
,double
, etc) bool
- structs
- enumerations
Reference-types include
- class
- interface
- object
- string
- ..etc
Passing value-type by value
When a value-type is passed by value, any changes to the parameter in the method will not be persisted back in the calling environment (Docs, 2015).
Passing reference-type by value
When a reference-type is passed by value, any changes to the reference/pointer/memory location of the parameter are local; but content of the parameter can be changed (Docs, 2015).
Changing the reference of the array parameter (ie. assigning it to a new array) will not be persisted:
void ChangeReference(int[] nums)
{
nums = new int[]{1, 2, 3, 4, 5};
}
void Main()
{
int[] numbers = new int[] { 10, 20, 30, 40 };
Console.WriteLine($"Original: {string.Join(", ", numbers)}");
ChangeReference(numbers);
Console.WriteLine($"After: {string.Join(", ", numbers)}");
}
Output:
Original: 10, 20, 30, 40
After: 10, 20, 30, 40
But changing the content of the array will be persisted:
void Main()
{
int[] numbers = new int[] { 10, 20, 30, 40 };
Console.WriteLine($"Original: {string.Join(", ", numbers)}");
ChangeContent(numbers);
Console.WriteLine($"After: {string.Join(", ", numbers)}");
}
void ChangeContent(int[] nums)
{
nums[0] = 1;
nums[1] = 2;
}
Output:
Original: 10, 20, 30, 40
After: 1, 2, 3, 40
Live-code example
Passing value-type by reference
When a value-type is passed by value, any changes to the parameter in the method will be persisted (Docs, 2015).
This can be achieved by using either ref
or out
keyword:
void Main()
{
int result;
Add(1, 2, out result);
Console.WriteLine(result);
}
void Add(int first, int second, out int result)
{
result = first + second;
}
Output:
3
Live-code example
Passing reference-type by reference
When a reference-type is passed by reference, any changes to the content and the reference/pointer/memory location of the parameter will be persisted (Docs, 2015).
In this case, changes to the reference of the array or the content of the array will both be persisted:
public static void Main()
{
int[] numbers = new int[]{10, 20, 30, 40};
int[] oldNumbers = numbers; // store a temporary reference to numbers
Console.WriteLine("--- Change reference/pointer/memory location");
Console.WriteLine($"Original: {string.Join(", ", numbers)}");
ChangeReference(ref numbers);
Console.WriteLine($"After: {string.Join(", ", numbers)}");
Console.WriteLine($"Still the same object? {numbers.Equals(oldNumbers)}");
oldNumbers = numbers;
Console.WriteLine();
Console.WriteLine("--- Change content");
Console.WriteLine($"Original: {string.Join(", ", numbers)}");
ChangeContent(ref numbers);
Console.WriteLine($"After: {string.Join(", ", numbers)}");
Console.WriteLine($"Still the same object? {numbers.Equals(oldNumbers)}");
}
static void ChangeReference(ref int[] nums)
{
nums = new int[]{1, 2, 3, 4, 5};
}
static void ChangeContent(ref int[] nums)
{
nums[0] = 100;
nums[1] = 200;
}
Output:
--- Change reference/pointer/memory location
Original: 10, 20, 30, 40
After: 1, 2, 3, 4, 5
Still the same object? False
--- Change content
Original: 1, 2, 3, 4, 5
After: 1, 2, 3, 4, 5
Still the same object? True
Live-code example
References
- Docs, M. (2015, July 20). Passing Parameters (C# Programming Guide). Retrieved from https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
- Docs, M. (2015, July 20). Value Types (C# Reference). Retrieved from https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/value-types
- Docs, M. (2015, July 20). Reference types (C# Reference). Retrieved from https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types
- Docs, M. (2015, July 20). Passing Value-Type Parameters (C# Programming Guide). Retrieved from https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-value-type-parameters
- Docs, M. (2015, July 20). Passing Reference-Type Parameters (C# Programming Guide). Retrieved from https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters