Introduction
In this guide, we will look at the difference between using in
, out
, and ref
when the passing reference and value types as parameters in C# methods. These techniques allow you to change how C# handles altering data locally in the method as well as outside the method.
The in, ref, and out Modifiers
Method parameters have modifiers available to change the desired outcome of how the parameter is treated. Each method has a specific use case:
ref
is used to state that the parameter passed may be modified by the method.in
is used to state that the parameter passed cannot be modified by the method.out
is used to state that the parameter passed must be modified by the method.
Both the ref
and in
require the parameter to have been initialized before being passed to a method. The out
modifier does not require this and is typically not initialized prior to being used in a method.
The ref Modifier
By default, a reference type passed into a method will have any changes made to its values reflected outside the method as well. If you assign the reference type to a new reference type inside the method, those changes will only be local to the method. See my Pluralsight guide Passing a Reference vs. Value for examples. Using the ref
modifier, you have the option to assign a new reference type and have it reflected outside the method.
1class ReferenceTypeExample
2{
3 static void Enroll(ref Student student)
4 {
5 // With ref, all three lines below alter the student variable outside the method.
6 student.Enrolled = true;
7 student = new Student();
8 student.Enrolled = false;
9 }
10
11 static void Main()
12 {
13 var student = new Student
14 {
15 Name = "Susan",
16 Enrolled = false
17 };
18
19 Enroll(ref student);
20
21 // student.Name is now null since a value was not passed when declaring new Student() in the Enroll method
22 // student.Enrolled is now false due to the ref modifier
23 }
24}
25
26public class Student {
27 public string Name {get;set;}
28 public bool Enrolled {get;set;}
29}
Using the ref
modifier, you can also change value types outside the method as well.
1class ReferenceTypeExample
2{
3 static void IncrementExample(ref int num)
4 {
5 num = num + 1;
6 }
7
8 static void Main()
9 {
10 int num = 1;
11 IncrementExample(ref num);
12 // num is now 2
13 }
14}
The out Modifier
Using the out
modifier, we initialize a variable inside the method. Like ref
, anything that happens in the method alters the variable outside the method. With ref
, you have the choice to not make changes to the parameter. When using out
, you must initialize the parameter you pass inside the method. The parameter being passed in often is null.
1class ReferenceTypeExample
2{
3 static void Enroll(out Student student)
4 {
5 //We need to initialize the variable in the method before we can do anything
6 student = new Student();
7 student.Enrolled = false;
8 }
9
10 static void Main()
11 {
12 Student student;
13
14 Enroll(out student); // student will be equal to the value in Enroll. Name will be null and Enrolled will be false.
15 }
16}
17
18public class Student {
19 public string Name {get;set;}
20 public bool Enrolled {get;set;}
21}
The out
modifier works with value types as well. A useful example is using the out
modifier to change a string to an int.
1int x;
2Int32.TryParse("3", out x);
The in Modifier
The in
modifier is most often used for performance reasons and was introduced in C# 7.2. The motivation of in
is to be used with a struct to improve performance by declaring that the value will not be modified. When using with reference types, it only prevents you from assigning a new reference.
1class ReferenceTypeExample
2{
3 static void Enroll(in Student student)
4 {
5 // With in assigning a new object would throw an error
6 // student = new Student();
7
8 // We can still do this with reference types though
9 student.Enrolled = true;
10 }
11
12 static void Main()
13 {
14 var student = new Student
15 {
16 Name = "Susan",
17 Enrolled = false
18 };
19
20 Enroll(student);
21 }
22}
23
24public class Student
25{
26 public string Name { get; set; }
27 public bool Enrolled { get; set; }
28}
Modifiers Are Not Allowed on All Methods
It's important to note that in
, out
, and ref
cannot be used in methods with the async
modifier. You can use them in synchronous methods that return a task, though.
You cannot use them in iterator methods that have a yield return
or yield break
either.
Overloading Methods with Modifiers
When overloading a method in C#, using a modifier will be considered a different method signature than not using a modifier at all. You cannot overload a method if the only difference between methods is the type of modifier used. This will result in a compile error.