.NET 8 and C# 12 — ref readonly Parameters

Henrique Siebert Domareski
4 min readNov 30, 2023

ref readonly parameters is a new C# 12 feature, which allows you to pass read-only references providing more clarity for APIs that might be using ref parameters or in parameters. In this article, I present which problem this feature solves and how to use it.

For demonstration purposes, I created a console application with .NET 8, and I ran the app using the Visual Studio 2022 Preview version.

Before going to the feature itself, let me explain which problem this feature solves. In the example below, you can see a class with a method to print a value in the console, and this method has a parameter of type int and is passed as a reference by using the ref keyword (note that int is a value type, but if you need to pass it by reference, you can use the keyword ref). This method reads the input number, prints it on the console and it sums the value 1:

public class RefOnlyParameters
public void Print(ref int number)
Console.WriteLine($"Your number is {number}");

This means that when running the following code, the output will be as following:

var refOnlyParametersDemo = new RefOnlyParameters();
var number = 5;

refOnlyParametersDemo.Print(ref number);
Console.WriteLine($"Your number is now {number}");

// Ouput:
Your number is 5
Your number is now 6

To avoid this situation, we can make use of the keyword in, and with that the compiler would issue an error (the in parameters feature was already available in C# 7.2):

Now with C# 12, it’s possible to achieve similar results by using the keywords ref readonly:

public void Print(ref readonly int number)
Console.WriteLine($"Your number is {number}");
number++; // This will make the compiler issue an error;

This is what you can see in Visual Studio:

With ref readonly it’s not possible then to change the value that is passed by reference, as it is a “read-only”.

With that said, you might be wondering, why this ref readonly feature was added, if it was already possible to do something similar using the in keyword? The reason for this, as it is in Microsoft’s Docs it’s for “APIs which capture or return references from their parameters would like to disallow rvalues and also enforce some indication at the callsite that a reference is being captured. ref readonly parameters are ideal in such cases as they warn if used with rvalues or without any annotation at the callsite.”.

“Rvalue”: stands for “right-hand side value”. It refers to a temporary or disposable value that appears on the right side of an assignment expression. It’s a value that doesn’t have a persistent memory location. For example, consider the expression int x = 5;. Here, 5 is an rvalue because it's a temporary value on the right side of the assignment. On the other hand, x is an lvalue because it represents a variable with a specific memory location.

“Lvalue”: stands for “left-hand side value. It refers to a value that has a persistent and identifiable memory location in the computer’s memory. Lvalues are typically used to represent variables or objects that can be assigned a new value. For example, in the assignment int x = 10;, the variable x is an lvalue because it represents a memory location where the value 10 is stored.


The introduction of the ref readonly feature addresses a specific need for APIs that handle references in their parameters that need to block values and enforce indication at the call site that a reference is being captured, providing more clarity for APIs that might be using ref parameters or in parameters.

This is the link for the project in GitHub: https://github.com/henriquesd/DotNet8Examples

If you like this demo, I kindly ask you to give a ⭐️ in the repository.

Thanks for reading!