Glossary / ref, out, and in
ref, out, and in
ref, out, and in pass variables by reference rather than by value, allowing a method to read or update the caller's storage under different definite-assignment and mutability rules. They are useful for APIs, interop, and performance-sensitive large structs, but create aliasing and lifetime constraints.
Semantics
ref requires the caller to initialize the variable and allows the callee to read and assign it. out requires the callee to assign it before returning; the caller need not initialize it first. in passes a readonly reference and requires a definitely assigned value. ref readonly and newer scoped/ref-safety features add nuanced restrictions. These modifiers affect overload signatures and call-site syntax; certain combinations are not distinct overloads.
static bool TryParse(string text, out int value) => int.TryParse(text, out value);
static void Inspect(in LargeStruct value) { }
Passing by reference can avoid copies but may introduce defensive copies for readonly structs/members, inhibit optimizations, or allow mutation through aliases. Ref returns and ref locals permit aliases to storage and are constrained so references cannot outlive referents. Async and iterator methods historically restrict ref-like usage; newer language versions selectively relax rules, so check target compiler/runtime.
Engineering guidance
Use out for established Try-pattern outputs; prefer return tuples/results for multiple related outputs when clearer. Use in only after measuring large value-copy cost. Avoid ref unless mutation/aliasing is central. Keep scopes short and understand thread-safety when references expose shared storage.
Interview questions
- What distinguishes out from ref? Out need not be initialized by caller but must be assigned by callee; ref is initialized input/output.
- What does in promise? The parameter is readonly through that reference in the callee.
- Can ref parameters be captured in lambdas? No, ref-like parameter restrictions prevent unsafe lifetime capture.
- Does in always improve performance? No; small structs and defensive copies can make it worse.
- What is a ref return? Returning an alias to existing storage, subject to escape/lifetime safety rules.