A ref parameter means the reference (pointer) to the value is provided to the called method rather than the object or value itself. This is useful if the method needs to modify the caller's variable or if the value is large, such as a big struct, and copying it would be costly.
in parameters C# 7.2 already let a method promise not to modify the value, but they also accept plain values such as new BigStruct(), silently passing a reference to a temporary copy. That makes in a poor fit for APIs that need a real variable, and changing an existing ref parameter to in was a breaking change for callers that pass ref.
In C# 12.0 a parameter can be declared ref readonly: the method cannot modify the value, and callers are expected to pass a variable.
Code
csharp
var bigStruct = new BigStruct();
Process(in bigStruct); // or ref bigStruct
Process(new BigStruct()); // warning: argument should be a variable
void Process(ref readonly BigStruct bigStructRef)
{
// bigStructRef = new BigStruct(); would fail
}csharp
var bigStruct = new BigStruct();
Process(in bigStruct);
Process(new BigStruct()); // allowed: passes a reference to a temporary copy
void Process(in BigStruct bigStructRef)
{
// bigStructRef = new BigStruct(); would fail
}Notes
- Callers pass the argument with
reforin; passing a variable without either, or a value that isn't a variable, produces a warning rather than an error