Programming
C# Language
Coding Tutorial
Software Development
Keyword Explanation

What's the difference between the 'ref' and 'out' keywords?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C#, both ref and out pass an argument by reference, which means the method works with the caller's variable instead of a copy. The difference is in the contract: ref expects an existing value, while out is for producing a value that the method must assign before returning.

What ref Means

A ref parameter is both input and output. The caller must initialize the variable before the call, and the method can read its current value and replace it.

csharp
1using System;
2
3class Program
4{
5    static void AddBonus(ref int score)
6    {
7        score += 10;
8    }
9
10    static void Main()
11    {
12        int score = 25;
13        AddBonus(ref score);
14        Console.WriteLine(score);
15    }
16}

Because the method reads the incoming value and then updates it, ref is a good fit.

What out Means

An out parameter is output only from the caller's perspective. The caller does not need to initialize the variable first, but the method must assign it before returning.

csharp
1using System;
2
3class Program
4{
5    static void GetCoordinates(out int x, out int y)
6    {
7        x = 10;
8        y = 20;
9    }
10
11    static void Main()
12    {
13        GetCoordinates(out int x, out int y);
14        Console.WriteLine($"{x}, {y}");
15    }
16}

The method is responsible for producing values, so out communicates that intent clearly.

The Practical Difference

The simplest way to remember the distinction is:

  • 'ref means “this variable already has a meaningful value”'
  • 'out means “this method will fill this variable in”'

That difference affects both readability and compiler rules. The compiler requires initialization before ref, but not before out. The compiler also enforces assignment inside the method for out parameters.

A Common Real-World Example

The classic out pattern is a Try... method such as int.TryParse.

csharp
1using System;
2
3class Program
4{
5    static void Main()
6    {
7        if (int.TryParse("123", out int value))
8        {
9            Console.WriteLine(value);
10        }
11    }
12}

The input is the string. The output is the parsed integer. out fits because the parsed result does not exist before the call.

When ref Is Appropriate

ref is useful when the method truly needs the current value and must update it in place. This is less common in everyday application code than many beginners expect.

csharp
1using System;
2
3class Program
4{
5    static void ClampToZero(ref int number)
6    {
7        if (number < 0)
8        {
9            number = 0;
10        }
11    }
12
13    static void Main()
14    {
15        int value = -5;
16        ClampToZero(ref value);
17        Console.WriteLine(value);
18    }
19}

The method reads the old value and decides how to mutate it, so ref makes sense.

API Design Considerations

Both keywords are powerful, but they also make method calls less straightforward because the called method can mutate external state. For public APIs, this should be a deliberate choice, not a habit.

In modern C#, alternatives such as tuples or small result objects can sometimes be clearer than multiple out parameters.

csharp
1using System;
2
3class Program
4{
5    static (int Width, int Height) GetSize()
6    {
7        return (800, 600);
8    }
9
10    static void Main()
11    {
12        var size = GetSize();
13        Console.WriteLine($"{size.Width} x {size.Height}");
14    }
15}

This avoids reference parameters entirely when that style is more readable.

Common Pitfalls

The most common mistake is using ref when the method never reads the incoming value. In that case, out usually expresses the contract better.

Another mistake is forgetting that out parameters must be assigned on every control path before the method returns. The compiler enforces this, but it still surprises many developers.

Developers also sometimes overuse ref and out in APIs where returning a tuple or object would make the code easier to understand.

Summary

  • Both ref and out pass arguments by reference.
  • 'ref requires initialization before the call and supports input plus output.'
  • 'out does not require initialization before the call and is meant for produced values.'
  • 'TryParse-style methods are classic out use cases.'
  • Use these keywords deliberately because they make mutation across method boundaries explicit.

Course illustration
Course illustration

All Rights Reserved.