Skip to main content

How to Resolve Error "CS0206: A non ref-returning property or indexer may not be used as an out or ref value" in C#

The Compiler Error CS0206 is a restriction related to memory management and the nature of Properties. The message reads: "A non ref-returning property or indexer may not be used as an out or ref value".

In C#, parameters marked with ref or out require the memory address of the variable being passed.

  • Fields represent direct memory locations, so they can be passed by reference.
  • Properties and Indexers are actually methods (getters and setters) disguised as fields. They do not represent a direct storage location; they represent a function call.

Because you cannot take the "memory address" of a method call, the compiler prevents you from passing a standard property as a ref or out parameter.

This guide explains why this limitation exists and how to work around it using temporary variables.

Understanding Properties vs. Fields

When you write myObject.MyField, you are accessing a box in memory. When you write myObject.MyProperty, the compiler translates this into myObject.get_MyProperty().

If you try to call Method(ref myObject.MyProperty), you are asking the compiler to pass the address of the get method's return value. Since that return value is temporary (it exists only on the stack for a microsecond), it has no permanent address to modify.

Scenario 1: Passing a Property as ref

The most common occurrence is trying to update a property using a helper method that modifies data via ref.

Example of error:

public class Player
{
// This is a Property (methods in disguise)
public int Score { get; set; }
}

public class Game
{
// A helper method that modifies the argument directly
public void AddPoints(ref int currentScore)
{
currentScore += 10;
}

public void Run()
{
Player p = new Player();

// ⛔️ Error CS0206: A non ref-returning property or indexer
// may not be used as an out or ref value.
// 'p.Score' is a method call, not a storage location.
AddPoints(ref p.Score);
}
}

Scenario 2: Lists vs. Arrays (Indexers)

This distinction often confuses developers.

  • Arrays (int[]): Are raw blocks of memory. Accessing array[0] gives you a direct memory slot. You can pass ref array[0].
  • Lists (List<int>): Use Indexers (this[int i]). These are methods. You cannot pass ref list[0].

Example of error:

using System.Collections.Generic;

public class DataProcessor
{
public void Process(ref int value)
{
value++;
}

public void Run()
{
int[] myArray = { 10, 20 };
List<int> myList = new List<int> { 10, 20 };

// ✅ Valid: Arrays expose direct memory addresses
Process(ref myArray[0]);

// ⛔️ Error CS0206: List access via [] is a method call (Indexer)
Process(ref myList[0]);
}
}

Solution 1: Use a Temporary Variable (Standard Fix)

The universal solution is to manually perform the steps that ref would do:

  1. Read the property into a local temporary variable.
  2. Pass the local variable (which has a memory address) to the method.
  3. Write the result back to the property.

Solution:

public class Player
{
public int Score { get; set; }
}

public class Game
{
public void AddPoints(ref int currentScore)
{
currentScore += 10;
}

public void Run()
{
Player p = new Player();

// 1. Read into temp variable
int tempScore = p.Score;

// 2. Pass temp variable (Safe)
AddPoints(ref tempScore);

// 3. Write back to property
p.Score = tempScore;

System.Console.WriteLine(p.Score);
}
}

Output:

10

Solution 2: Use a Backing Field

If you are writing code inside the class that owns the property, you can bypass the property and pass the private backing field instead. Fields are valid ref targets.

Solution:

public class Player
{
// Explicit backing field
private int _score;

public int Score
{
get { return _score; }
set { _score = value; }
}

private void Modify(ref int val)
{
val += 10;
}

public void Update()
{
// ✅ Correct: '_score' is a field, so we can pass its address.
Modify(ref _score);
}
}
note

Ref Returns (C# 7.0+): Modern C# supports "Ref Returns" which allow properties to return a reference to their storage storage (ref int MyProp { get { return ref _field; } }). If a property is defined this way, CS0206 does not apply. However, most standard properties are not ref-returning.

Conclusion

CS0206 enforces the difference between storage (Fields) and accessors (Properties).

  1. Identify the Target: Are you passing a Property (obj.Prop) or an Indexer (list[0]) to a ref/out parameter?
  2. The Fix: Introduce a local variable.
    • var temp = obj.Prop;
    • Method(ref temp);
    • obj.Prop = temp;
  3. Internal Logic: If inside the class, pass the private backing field instead.