C# - Ref Keyword

Learn how to use a ref keyword with reference types in C#.

I have written this blog for Ref keyword though there are many blogs and articles available around this. But I have noticed some very specific behavior when dealing with Ref keyword.
 
In C#, variables are of two types - Value Type and Reference Type. Ref keyword can be used for these two types which means we are handling these types by their references.
 
There are some differences when we are using with Ref and without Ref. To use the Ref keyword, there are three rules (these are the main differences with the Out keyword),
  • Rule 1: Variable should be initialized before use
  • Rule 2: Call the method with ref keyword in prefix
  • Rule 3: Receive variable in method with ref keyword in prefix
Let’s see some code here and try to understand the differences.
 

Value Type with Ref keyword

  1. class Program {  
  2.     static void Main(string[] args) {  
  3.         int valueTypeA = 10; // Rule 1: Variable should be initialized before use  
  4.         MethodWithOutRef(valueTypeA);  
  5.         Console.WriteLine(valueTypeA); //Output: 10, As the modification was in local scope of MethodWithOutRef  
  6.         MethodWithRef(ref valueTypeA); // Rule 2: Call the method with ref keyword in prefix  
  7.         Console.WriteLine(valueTypeA); //Output: 12, Here is the magic of Ref  
  8.         Console.Read();  
  9.     }  
  10.     static void MethodWithOutRef(int recVar) {  
  11.         recVar = 12; //modifiy the value to 12  
  12.     }  
  13.     static void MethodWithRef(ref int recVar) // Rule 3: Receive variable in method with ref keyword in prefix  
  14.     {  
  15.         recVar = 12; //modify the value to 12  
  16.     }  
  17. }  
Code Explanation
 
As we see that with Ref keyword, the output is 12, this is because we passed the reference. Both valueTypeA and recVar are pointing to the same variable that’s why recVar modify the actual value.
 

Reference Type with Ref keyword

 
Reference Type has a little bit more complex mechanism than Value Type. Whenever we are passing the Reference Type (Object) in any method that means we are passing the reference.
  1. When we are passing any Reference Type that means we are passing a reference (Pointer) of the actual object.
  2. When we are passing any Reference Type with Ref keyword that means we are passing the actual object (Pointer to pointer). 
What does this mean? Let’s see in the example.
  1. class Program {  
  2.     static void Main(string[] args) {  
  3.         var obj = new TestReferenceType {  
  4.             IntProp = 10, StrProp = "First"  
  5.         }; // Rule 1: Object should be initialized before use  
  6.         MethodWithOutRef(obj);  
  7.         Console.WriteLine(obj.IntProp); //Output : 12  
  8.         Console.WriteLine(obj.StrProp); //Output : Second  
  9.         MethodWithRef(ref obj); // Rule 2: Call the method with ref keyword in prefix  
  10.         Console.WriteLine(obj.IntProp); //Output : 14  
  11.         Console.WriteLine(obj.StrProp); //Output : Third  
  12.         Console.Read();  
  13.     }  
  14.     static void MethodWithOutRef(TestReferenceType recVar) {  
  15.         recVar.IntProp = 12; //modifiy the value to 12  
  16.         recVar.StrProp = "Second"//modify the value to Second  
  17.     }  
  18.     static void MethodWithRef(ref TestReferenceType recVar)  
  19.     // Rule 3: Receive variable in method with ref keyword in prefix  
  20.     {  
  21.         recVar.IntProp = 14; //modify the value to 14  
  22.         recVar.StrProp = "Third"//modify the value to Third  
  23.     }  
  24. }  
  25. class TestReferenceType {  
  26.     public int IntProp {  
  27.         get;  
  28.         set;  
  29.     }  
  30.     public string StrProp {  
  31.         get;  
  32.         set;  
  33.     }  
  34. }  
Code Explanation
 
Here, the output is kind of the same in both With Ref and Without Ref. Modifying the properties by the actual object or by reference of the actual object, we are talking about the same thing. That’s why the behavior is the the same in the above example.
 
Now, let’s change a little bit and see the magic of Ref keyword in reference Type. In the below example, I have added just one line in methods.
  1. [recVar = new TestReferenceType();]  
  2. class Program {  
  3.     static void Main(string[] args) {  
  4.         var obj = new TestReferenceType {  
  5.             IntProp = 10, StrProp = "First"  
  6.         };  
  7.         // Rule 1: Object should be initialized before use  
  8.         MethodWithOutRef(obj);  
  9.         Console.WriteLine(obj.IntProp); //Output : 10  
  10.         Console.WriteLine(obj.StrProp); //Output : First  
  11.         // Actual object is remaining same but the passing reference has been modified and pointing to the new memory  
  12.         MethodWithRef(ref obj); // Rule 2: Call the method with ref keyword in prefix  
  13.         Console.WriteLine(obj.IntProp); //Output : 14  
  14.         Console.WriteLine(obj.StrProp); //Output : Third  
  15.         //Actual object has been modified with new object.  
  16.         Console.Read();  
  17.     }  
  18.     static void MethodWithOutRef(TestReferenceType recVar) {  
  19.         recVar = new TestReferenceType();  
  20.         //Here recVar is reference and it has been overwritten, now it is pointing to new object.  
  21.         recVar.IntProp = 12; //modify the value to 12  
  22.         recVar.StrProp = "Second"//modify the value to Second  
  23.     }  
  24.     static void MethodWithRef(ref TestReferenceType recVar)  
  25.     // Rule 3: Receive variable in method with ref keyword in prefix  
  26.     {  
  27.         recVar = new TestReferenceType(); // Here recvar is actual object and we are changing the actual object  
  28.         recVar.IntProp = 14; //modify the value to 14  
  29.         recVar.StrProp = "Third"//modify the value to Third  
  30.     }  
  31. }  
  32. class TestReferenceType {  
  33.     public int IntProp {  
  34.         get;  
  35.         set;  
  36.     }  
  37.     public string StrProp {  
  38.         get;  
  39.         set;  
  40.     }  
  41. }  
Code Explanation
 
When we pass a reference of an object in a method, there are two possibilities with the passing reference,
  • Modification in Values (Properties)- Then object will be modified in the caller.
  • Modification in Object (by the new operator) – Then caller object will not be modified.
When we pass a reference of an object with Ref keyword in a method, there are two possibilities with the passing reference,
  • Modification in Values (Properties)- Then object will be modified in the caller.
  • Modification in Object (by the new operator) – Then object will be modified in the caller.
Another important thing is Method Overloading.
 
We can overload the methods by using Ref keyword like below.
  1. Class A  
  2. {  
  3.    public void SampleMethod(int i) { }  
  4.    public void SampleMethod(ref int i) { }  
  5. }  
But we can’t overload in between Ref and Out as below.
  1. Class A  
  2. {  
  3.    public void SampleMethod(out int i) { }  
  4.    public void SampleMethod(ref int i) { }  
  5. // Compiler error CS0663: "Cannot define overloaded // methods that differ only on ref and out".  
We can't use the ref and out keywords for the following kinds of methods. Async methods you can define by using the async modifier. Iterator methods include a yield return or yield break statement.