out, ref, and in Parameters

C# 7.2 NETCore 2.1

Published Updated Author Jeffrey T. Fritz Reading time

Control argument passing by reference to return extra values, mutate callers, or avoid copies for readonly inputs.

Reference parameter modifiers solve different problems: out returns a value through an argument, ref allows caller-visible mutation, and in (C# 7.2) passes by reference while keeping the argument readonly.

Why it matters

  • Avoids tuple allocations and exception-heavy parse flows in hot paths.
  • Enables explicit mutation semantics with ref.
  • Improves performance for large structs via in without sacrificing safety.

Cautions

Use these modifiers intentionally because they affect API ergonomics. ref and out can make call sites noisier and harder to compose. Prefer clear names and keep referenced data lifetimes straightforward.

Use out for parse-style APIs

out parameters return extra values while signaling success or failure.

Valid since C# 7.0

using System;

if (int.TryParse("123", out int value))
{
    Console.WriteLine(value + 1);
}
else
{
    Console.WriteLine("Invalid number");
}

Use ref when caller state should be updated

ref parameters let methods modify caller variables directly.

Valid since C# 7.0

using System;

static void Increment(ref int number)
{
    number++;
}

int count = 10;
Increment(ref count);
Console.WriteLine(count); // 11

Use in for readonly pass-by-reference

in passes large value types by reference while preventing modification.

Valid since C# 7.2

using System;

public readonly struct Vector3
{
    public Vector3(double x, double y, double z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public double X { get; }
    public double Y { get; }
    public double Z { get; }
}

public static class Program
{
    private static double Length(in Vector3 value)
    {
        return Math.Sqrt((value.X * value.X) + (value.Y * value.Y) + (value.Z * value.Z));
    }

    public static void Main()
    {
        var vector = new Vector3(3, 4, 12);
        Console.WriteLine(Length(in vector));
    }
}

Learn more

Method parameters (Microsoft Learn)