Important Update
The Guide Feature will be discontinued after December 15th, 2023. Until then, you can continue to access and refer to the existing guides.
Author avatar

Matt Ferderer

Using in, out, and ref with Parameters in C#

Matt Ferderer

  • Oct 13, 2020
  • 6 Min read
  • 253,845 Views
  • Oct 13, 2020
  • 6 Min read
  • 253,845 Views
Programming languages
C#

Introduction

In this guide, we will look at the difference between using in, out, and ref when 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.

Before reading this article, you should have an understanding of passing reference and value types.

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}
csharp

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}
csharp

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}
csharp

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);
csharp

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}
csharp

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.

Conclusion

Knowing these simple techniques can make your code easier to understand &and simpler to read.

To learn more about passing reference types, value types, and other types in C# check out Accelerated C# Fundamentals by Scott Allen. Don't forget to try out the C# Path and see where your skills are at and where you can improve!

About the Author

Matt Ferderer is a software developer who tweets, posts and blogs about web development.

Learn More

Explore these C# courses from Pluralsight to continue learning: