static void ConsumeRefReadonly(ref readonly int i) { /* do something */ }
static void ConsumeIn(in int i) { /* do something */ }
static void Test() {
// Passing an lvalue (a value that has a memory location) requires the 'ref' keyword for the ref-readonly method only:
var i = 3;
ConsumeRefReadonly(ref i);
ConsumeIn(i);
// The 'ref' modifier is required on arguments to ref-readonly parameters, and is not recommended on arguments to in parameters.
// Swapping the 'ref' keyword presence compared to the last example emits warnings in both places:
ConsumeRefReadonly(i); // Compiles with warning: "Argument 1 should be passed with 'ref' or 'in' keyword"
ConsumeIn(ref i); // Compiles with warning: "The 'ref' modifier for argument 1 corresponding to 'in' parameter is equivalent to 'in'."
// Passing rvalues (a value that may or may not have a memory location) is permitted in both cases, but emits a warning for ref-readonly arguments:
ConsumeRefReadonly(123); // Compiles with warning: "Argument 1 should be a variable because it is passed to a 'ref readonly' parameter"
ConsumeIn(123);
}
Code snippet taken from "Complete C# Quick Reference - C# 12".