Before discussing about the ref and out it is good to know about the two varieties of data types in c# - value type and reference type. As the name indicates, the value type variable holds the real data and the reference type variable holds a reference(pointer) to data. When a variable is declared using one of the basic, built-in data types or a user defined structure, it is a value type. An exception is the string data type, which is a reference type. Variable of a class or an array is a reference type.
Value types are stored in stack and reference types are stored in heap memory.When you are declaring a variable of reference type, the variable never holding data; data are on the heap and a reference to the heap address is stored on the stack. When you are passing a value type to a method, the value in the variable is passed to the called method and there a local copy of the value is created on the stack and the called method is really working on that local copy while the orginal value remains unchanged. When the called method returns, the calling method takes back the orginal value not the local copy.
People are greatly confused with the reference type and the pass by reference. Even if we are passing a reference type to method, basically it is passed by value. As you know the reference type variable is not holding the data, rather it holds the reference to the data and that (reference) is stored in the stack itself. When a reference type is passed to a method, it is only the address of the data is passed and the called method makes a local copy of the address to work with. Since both the calling and called methods is having the same address they can share the data pointed by that address. But if the passed parameter is reinitialized or otherwise assigned to a different reference it won't reflected in called method.
To give you more understanding, let's look into the following example.
class Program
{
static void Main(string[] args)
{
Employe emp = new Employe{ ID = 1, Name ="Anu" };
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :1, Name : Anu
changeEmploye(emp);
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :2, Name : Anu Pushkaran
}
public class Employe
{
public int ID;
public string Name;
}
static void changeEmploye(Employe employe)
{
employe.ID = 2;
employe.Name = "Anu Pushkaran";
}
}
We created a variable emp of type Employe in main() method and initialized the field ID to 1 and Name to "Anu" . After that variable emp is passed it to the changeEmploye() method where we changed the values of the fileds. As printed in the console, the values set inside initEmploye()method is got reflected in the main() method. This behaviour is confucing us. Actually variable emp in the main() method and employe in the initEmploye() method are two distinct variables and the reference to the Employe object got passed by value to employe variable in the initEmploye() method. Since both variable are hodlding the same reference pointing to the same data, we are able to read/set the values from both methods.
Now look into the small change that i have introduce in changeEmploye().
class Program
{
static void Main(string[] args)
{
Employe emp = new Employe{ ID = 1, Name ="Anu" };
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :1, Name : Anu
changeEmploye(emp);
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :1, Name : Anu
//Eventhough we passed a reference type, once a new object
//is assigned with in the called function, it won't reflect
//to calling function
}
public class Employe
{
public int ID;
public string Name;
}
static void changeEmploye(Employe employe)
{
employe = new Employe();
employe.ID = 2;
employe.Name = "Anu Pushkaran";
}
}
Inside the changeEmploye() method we created another object of Employe with new values and assigned the new object to employe variable. Now when we tried to read the values inside the main() method, the emp variable is having the old values.Why?. Before assigning a new object both the emp and employe varibles were held the same reference and later the employe variable is holding reference to the new object data while the emp is holding the same reference to to the old data. Ie, if the passed parameter is reinitialized or otherwise assigned to a different reference it won't reflected in called method.
Hope now you got passing a reference type to a method is not equal to pass by reference. So to do actual pass by reference, we should use ref or out key words. In this case even if the passed parameter is reinitialized or otherwise assigned to a different reference it will reflect in the called method.
class Program
{
static void Main(string[] args)
{
Employe emp = new Employe{ ID = 1, Name ="Anu" };
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :1, Name : Anu
changeEmploye(ref emp);
Console.WriteLine("ID : " + emp.ID + ", Name : " +emp.Name);
// Output-> ID :2, Name : Anu Pushkaran
//Eventhough we reinilialized the variable inside
// changeEmploye(), the changes are reflectig
}
public class Employe
{
public int ID;
public string Name;
}
static void changeEmploye(ref Employe employe)
{
employe = new Employe();
employe.ID = 2;
employe.Name = "Anu Pushkaran";
}
}
In pass by reference scenario, there will not create any local copy of the passed parameter. Here both the variables (in the calling and called methods) work on the same copy and hence the changes will get reflected when the calling method returns even if the passed parameter is reinitialized or re-assigned.
Both ref and out are used to achive pass by reference?
Yes, both are used for achieving pass by reference with some difference as below.
- The argument must be initialized first before it is passed to ref, but it's not mandatory for out.
- It is not required to assign or initialize the value of a parameter passed by ref before returning to the calling method. A called method is required to assign or initialize a value of a parameter which is passed to an out before returning to the calling method.
- When we use ref, data can be passed bi-directionally.When we use out data is passed only from the called method to the caller method.
Where to use ref and out?
- When we need to return multiple values from a method.
- To boost performance.
A function can return only one return value. We can use ref and out when we need to return multiple values from amethod.
When data is passed into methods as value type parameters, a copy of each parameter is created on the stack. Clearly, if the parameter is a larger data type, such as a user-defined structure with many elements, or the method is executed many times, this may have an impact on performance.
ref or out?
If called methods need the value of passing parameter we have to use ref. If the called method just wanted to return and no need to read the passed value, we have to use out. out makes a big difference when the data needs to be marshalled to another process, which can be costly. Using out we can avoid marshalling if the the method doesn't make use of initial value.






