Introduction
We have two keywords named ref and out in C#. These keywords help in situations when we need to return more than one value from a method. But there is more important point in the use of the ref keyword. As per MSDN, ref means:
"The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the called method is reflected in the calling method."
This means if we are passing any method parameter (either value type or reference type) using ref parameter, any change in the parameter value inside the method will be reflected back into the actual value of parameter. Let's try to understand this with an example.
We have a method named GetData which takes an integer parameter. Inside the method, we will update this value. Then, we call this method and print the value of the parameter - before method call, inside the method, and after the execution of the method. So, the code will look like the following.
Run the application and see the results. The value of the parameter is different inside the method but it is same as before and after the method call. The output will be.
Value before method call is: 4
Value inside method is: 1003
Value after method call is: 4
Now, we change the parameter and associate the ref keyword with it. We again call this method and print its values. So, the code will look like the following.
public static void GetData(ref int a)
{
a = a + 999;
Console.WriteLine("Value inside method is: " + a);
}
Run the application and see the difference between this result and the results with first execution.
Value before method call is: 4
Value inside method is: 1003
Value after method call is: 1003
This time, the value of the parameter after the method execution is same to what it was set inside the method. The reason behind is that the use of ref keyword causes the parameter to be passed by reference and not by actual value. In other words, the actual parameter value was shared with the method due to use of ref keyword. So any changes in the value of parameter inside the method, updated the original value as well.
Now, let's try to see the same thing with a reference type. We add a new class named TestClass and add two properties named Id and Name. We change method signature to pass a parameter of type TestClass, without the ref keyword. Inside the method, we re-initialize the class TestClass type and update the values of the properties. Again we print the values before the method call, inside the method and after the method call. So the code will look like following,
static void Main(string[] args)
{
TestClass testClass = new TestClass()
{
Id = 1,
Name = "Test User"
};
Console.WriteLine("Before method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
GetData(testClass);
Console.WriteLine("After method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
Console.ReadKey();
}
public static void GetData(TestClass testClass)
{
testClass = new ConsoleApplication1.Program.TestClass();
testClass.Id += 999;
testClass.Name += "_Updated";
Console.WriteLine("Inside method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
}
public class TestClass
{
public int Id
{
get;
set;
}
public String Name
{
get;
set;
}
}
Run the code and see the results.
- Before method call Name is: Test User and ID is:1
- Inside method call Name is: _Updated and ID is:999
- After method call Name is: Test User and ID is:1
As we know that the reference type variables contain a pointer to the data and not the actual data, so when we passed the the parameter to method, we actually shared a copy of the pointer with the method and not the actual pointer. When the parameter is re-initialized inside the method, we created a new pointer which replaced the copy of pointer (received in the method call). So the data got changed inside the method but remained same after the execution of the method. Now let's change the method to pass the pointer of data using ref keyword.
static void Main(string[] args)
{
TestClass testClass = new TestClass()
{
Id = 1,
Name = "Test User"
};
Console.WriteLine("Before method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
GetData(ref testClass);
Console.WriteLine("After method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
Console.ReadKey();
}
public static void GetData(ref TestClass testClass)
{
testClass = new ConsoleApplication1.Program.TestClass();
testClass.Id += 999;
testClass.Name += "_Updated";
Console.WriteLine("Inside method call Name is: " + testClass.Name + " and ID is:" + testClass.Id);
}
Run the code and see the difference in the results.
- Before method call Name is: Test User and ID is:1
- Inside method call Name is: _Updated and ID is:999
- After method call Name is: _Updated and ID is:999
This time, the values got changed after the execution of the method as well. The reason being, this time we shared the actual pointer with the method and not it's copy. So changes in the pointer (by the re-initialization of TestClass inside the method), updated the original pointer (testClass instance in Main method). So new values were printed after method execution. This is what msdn says i.e.The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the called method is reflected in the calling method.
So, it becomes very important to decide whether we want to use the ref or out keyword, especially when the parameter types are value types. Hope you enjoyed reading this article. Happy coding...!!!