We use ref
and out
keywords to pass parameters to a method. What exactly the different between these 2 keywords?
Here is an example:
// A simple example for usage of Ref keyword in C# static void Main(string[] args) { int myVariable = 5; string returnText = PrintNumber(ref myVariable); Console.WriteLine(returnText); } public static string PrintNumber(ref int myVariable) { string returnText = "Result: " + myVariable.ToString(); return returnText; }
Output:
You may ask: “Why do we need to use ref
or out
? Can’t we just pass the parameter without using them?. The answer is “Yes”. However, if you don’t use ref
or out
, the parameters are sent to methods as values by default. It means, the parameter you pass becomes a new variable in the called method. If you change its value, the variable in the main method won’t change.
In contrast, if you use ref
or out
keywords, parameter is passed to the method as reference. It means, it is still the same variable in the main method and called method. If you change the value of this variable, the value of the variable in the main method will change too.
Here is the extended version of our example above:
// Changing the value of the parameter passed by Ref keyword in C# static void Main(string[] args) { int myVariable = 5; Console.WriteLine("Initial value (in the main method): " + myVariable.ToString()); string returnText = PrintNumber(ref myVariable); Console.WriteLine("New value (in the main method): " + returnText.ToString()); } public static string PrintNumber(ref int myVariable) { Console.WriteLine("Initial value (in the called method): " + myVariable.ToString()); myVariable++; Console.WriteLine("New value (in the called method): " + myVariable.ToString()); return myVariable.ToString(); }
Output:
Difference between Ref and Out keywords
The main difference is that you have to initialize (or assign a value to) variable in the main method before passing it by ref
keyword. However, you don’t have to initialize it in the main method if you are passing it by out
parameter.
// The example that shows the difference between ref and out keywords in C# static void Main(string[] args) { int myVariable = 5; string returnText1 = PrintNumber1(ref myVariable); string returnText2 = PrintNumber2(out myVariable); Console.WriteLine("Passed by ref: " + returnText1.ToString()); Console.WriteLine("Passed by out: " + returnText2.ToString()); Console.ReadLine(); } public static string PrintNumber1(ref int myVariable) { // No initialization here return myVariable.ToString(); } public static string PrintNumber2(out int myVariable) { myVariable = 6; // It must be initialized here return myVariable.ToString(); }
Output:
In the called method, if you don’t initialize a parameter passed by out
keyword, you will receive the error messages below:
The out parameter ‘myVariable’ must be assigned to before control leaves the current
Use of unassigned out parameter ‘myVariable’
Comparison table
Ref | Out |
The parameter must be initialized before it is passed a method | Parameter doesn’t have to be initialized in the main method |
It is not required to initialize (or assign a value to) the parameter in the called method | Parameter has to be initialized or a value should be assigned to it in the called method |
Ref is useful when the called method needs to modify the passed parameter | Out is useful when multiple values need to be returned from a function or method |
Data can be passed bi-directionally. It work two-ways | Data is passed only one-way (from the called method to the main method) |
Notes:
- Both
ref
andout
keywords are treated the same at compile time but they are treated differently at run time - Properties cannot be passed by
ref
orout
keywords
Bonus 1:
Starting from C# 7.0, you can declare variables on the fly while calling a method with out
parameter:
int.TryParse("123", out int x); Console.WriteLine(x);
The code lines above are equivalent to the following lines:
int x; int.TryParse("123", out x); Console.WriteLine(x);
Bonus 2:
You don’t have to pass variables/values for every out
parameter defined by a method. You can ignore out
parameters by simply passing an underscore (_). For example:
TestMethod(out _, out _, out int number, out _)
In the example above, we ignored all out
parameters except the third one.