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
- class Program {
- static void Main(string[] args) {
- int valueTypeA = 10;
- MethodWithOutRef(valueTypeA);
- Console.WriteLine(valueTypeA);
- MethodWithRef(ref valueTypeA);
- Console.WriteLine(valueTypeA);
- Console.Read();
- }
- static void MethodWithOutRef(int recVar) {
- recVar = 12;
- }
- static void MethodWithRef(ref int recVar)
- {
- recVar = 12;
- }
- }
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.
- When we are passing any Reference Type that means we are passing a reference (Pointer) of the actual object.
- 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.
- class Program {
- static void Main(string[] args) {
- var obj = new TestReferenceType {
- IntProp = 10, StrProp = "First"
- };
- MethodWithOutRef(obj);
- Console.WriteLine(obj.IntProp);
- Console.WriteLine(obj.StrProp);
- MethodWithRef(ref obj);
- Console.WriteLine(obj.IntProp);
- Console.WriteLine(obj.StrProp);
- Console.Read();
- }
- static void MethodWithOutRef(TestReferenceType recVar) {
- recVar.IntProp = 12;
- recVar.StrProp = "Second";
- }
- static void MethodWithRef(ref TestReferenceType recVar)
-
- {
- recVar.IntProp = 14;
- recVar.StrProp = "Third";
- }
- }
- class TestReferenceType {
- public int IntProp {
- get;
- set;
- }
- public string StrProp {
- get;
- set;
- }
- }
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.
- [recVar = new TestReferenceType();]
- class Program {
- static void Main(string[] args) {
- var obj = new TestReferenceType {
- IntProp = 10, StrProp = "First"
- };
-
- MethodWithOutRef(obj);
- Console.WriteLine(obj.IntProp);
- Console.WriteLine(obj.StrProp);
-
- MethodWithRef(ref obj);
- Console.WriteLine(obj.IntProp);
- Console.WriteLine(obj.StrProp);
-
- Console.Read();
- }
- static void MethodWithOutRef(TestReferenceType recVar) {
- recVar = new TestReferenceType();
-
- recVar.IntProp = 12;
- recVar.StrProp = "Second";
- }
- static void MethodWithRef(ref TestReferenceType recVar)
-
- {
- recVar = new TestReferenceType();
- recVar.IntProp = 14;
- recVar.StrProp = "Third";
- }
- }
- class TestReferenceType {
- public int IntProp {
- get;
- set;
- }
- public string StrProp {
- get;
- set;
- }
- }
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.
- Class A
- {
- public void SampleMethod(int i) { }
- public void SampleMethod(ref int i) { }
- }
But we can’t overload in between Ref and Out as below.
- Class A
- {
- public void SampleMethod(out int i) { }
- public void SampleMethod(ref int i) { }
- }
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.