Introduction
Before understanding the ref and out keywords, it is necessary to understand what value and reference types are, so let us start with reference types.
Reference types are a pointer type that stores a memory address that points to a memory location in heap memory. Here the key point is that a reference type uses both the stack and the heap. That means it stores the address in the heap, and the value is stored in the stack, so it means that without the stack, there is no heap at all.
Example. All user-defined classes.
Value types are those that directly store a value inside it and that use stack memory.
Example. All pre-defined data types. (For example int, float, double, and so on.),
Note. For example, I do like this.
int x = 4;
int x1 = x; // This assigns the value of x (which is 4) to x1.
// Now, if you want to change the value of x to 100, you can do this:
x = 100; // This updates the value of x to 100.
And if we print x1, the output we get is 4 only, so it cannot be changed because it holds the value directly, but if a reference type changes in one type, it must be reflected in another type.
Now let's start with our main topic, the ref, and our keywords.
Ref Keyword in C#
The ref keyword can be used with any data type. The main purpose of the ref keyword is to make any type a reference type; in other words, when we add a ref keyword in a method call, then the C# compiler does not create a new variable, it just creates a copy of that type that only points to that specific variable that we declared and any changes made to that variable will be reflected in that variable. For example, we do it like.
using System;
class Program
{
static void Main()
{
int x = 10;
Show(ref x);
}
static void Show(ref int x)
{
// Method declaration
}
}
Public static show (ref int number) //Here it does not create a new variable, rather it makes a copy of that type so any changes made to it is reflected to the original variable, That's how ref is used in primitive data type.
Example
using System;
class RefDemo
{
public static void Show(ref int number)
{
number = 23;
}
static void Main()
{
int x = 10;
Show(ref x);
Console.WriteLine(x); // This will print 23
}
}
In the preceding, the output is 10 because all value type variables are directly storing a value due to this, here if we print the number we get the output as 23, and for x, we get 10.
But it is changed when we call this method using the ref keyword. That can be as in the following.
using System;
class RefDemo
{
public static void Show(ref int number)
{
number = 23;
}
static void Main()
{
int x = 10;
Show(ref x);
Console.WriteLine(x); // This will print 23
}
}
Here we got the output as 23 because the C# compiler doesn't create a variable. It makes a copy of type x. So the changes made anywhere are reflected to x.
A class or all reference type variables also do that. As we know, in the case of a class type without using ref also point to the same object when we assign one object to a class variable. Consider Case 1.
Case 1
using System;
class GradeData
{
public string name;
}
class RefDemo
{
public static void Show(GradeData data)
{
data.name = "SURYA";
}
static void Main()
{
GradeData obj = new GradeData();
GradeData obj1 = new GradeData(); // Create a new instance of GradeData
obj1.name = "Rajani";
obj1 = obj; // Assign obj to obj1
Show(obj1); // Pass obj1 to the Show method
Console.WriteLine(obj1.name); // This will print "SURYA"
}
}
Consider the second case.
Case 2
using System;
class GradeData
{
public string name;
}
class RefDemo
{
public static void Show(GradeData data)
{
data = new GradeData(); // Create a new GradeData object
data.name = "SURYA";
}
static void Main()
{
GradeData obj = new GradeData();
GradeData obj1 = new GradeData();
obj1.name = "Rajani";
obj1 = obj; // Assign obj to obj1
Show(obj1); // Pass obj1 to the Show method
Console.WriteLine(obj1.name); // This will print "Rajani" because obj1 still references the same object as obj
}
}
Example
using System;
class GradeData
{
public string name;
}
class RefDemo
{
public static void Show(ref GradeData data)
{
data = new GradeData(); // Modify the object referred to by data
data.name = "SURYA";
}
static void Main()
{
GradeData obj = new GradeData();
GradeData obj1 = new GradeData();
obj1.name = "Rajani";
obj1 = obj; // Assign obj to obj1
Show(ref obj1); // Pass obj1 by reference to the Show method
Console.WriteLine(obj1.name); // This will print "SURYA" because obj1 now references a new object
}
}
Due to the use of the ref keyword, the C# compiler treats the data object as a copy of the obj1 type, so any changes made to the data are reflected in obj1/obj.
Note. Before we use the ref keyword in a call a method, it must be initialized, whether it is a value type or a ref type.
Out keyword in C #
The out is also used for the same purpose, and we can use it for both a value type and a reference type, but the following is the main difference.
Before calling the method using the ref keyword, we must allocate the variable used in that method, whereas for an out, we need not assign the value before calling the method. In other words, the C# compiler does 't care about whether you are assigned or not, but it is necessary when the controller goes to a specific method. In that method, we must initialize the variable before the control flows out of that method.
Another difference is that when out is used with a value type, then we can return more than one value from a method at a time.
Example
using System;
class OutDemo
{
public static void GetData(int c, out int a, out int b)
{
a = c + 5;
b = c + a;
}
public static void Main()
{
GetData(5, out int a, out int b);
Console.WriteLine(a);
Console.WriteLine(b);
Console.ReadLine();
}
}
Important Key Capsule
Remember that during compilation, both the out and ref keywords are not considered by the CSC compiler. It only checks the standard language infrastructure, so if you are writing like this.
public static void GetDataRef(ref int a)
{
// Your code here
}
public static void GetDataOut(out int a)
{
// Your code here
}
If and think that it is an overloaded method, then you are wrong. Both are the same only. Here the C# compiler does not consider ref and out as a parameter, so it shows an error at runtime.
I think the preceding has given you a clear picture of ref and out.
Thanks for reading. I hope this is useful for you.