C# Ref Return — Complete Guide
In this tutorial, you'll learn about C# Ref Return. We cover key concepts, practical examples, and best practices.
A method returns a value from an array or a large struct. Every call copies the value. If you want to modify the original or avoid the copy, you previously used unsafe code or out parameters. Ref returns let you return a reference to the original location.
Wrong
public int GetMax(int[] numbers)
{
int maxIndex = 0;
for (int i = 1; i < numbers.Length; i++)
if (numbers[i] > numbers[maxIndex]) maxIndex = i;
return numbers[maxIndex]; // Returns a copy
}
Output: Returns the max value. Caller cannot modify the array through this method.
Right
public ref int GetMax(int[] numbers)
{
int maxIndex = 0;
for (int i = 1; i < numbers.Length; i++)
if (numbers[i] > numbers[maxIndex]) maxIndex = i;
return ref numbers[maxIndex]; // Returns a reference
}
// Usage
ref int max = ref GetMax(scores);
max = 100; // Modifies scores[maxIndex] directly!
Console.WriteLine(scores[2]); // 100
Output: The array element is modified through the reference. No copying.
Ref returns can also avoid copying large structs:
public ref readonly LargeStruct GetItem(int index)
{
return ref _items[index]; // Read-only ref — no copy, no mutation
}
Prevention
- Use
ref returnto return references to existing data (array elements, fields, etc.). - Use
ref readonlyreturn to avoid copying without allowing mutation. - Use
ref returnwithreflocal variables for in-place modification. - Ensure the ref return target outlives the method (no ref to local variables).
- Use
ref returnfor indexers on custom collections. - Use
ref returnin high-performance code where copying large structs is costly.
Common Mistakes with ref return
- Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto exit a function early instead of wrapping a pure value in the monad - Mixing let bindings with <- bindings in do notation, producing type errors
These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Ref returns are used in DodaZIP's archive parser to provide direct access to compressed data without copying. For more C#, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro