How to Resolve Error "CS0685: Conditional member 'member' cannot have an out parameter" in C#
The Compiler Error CS0685 is a logical safety error involving the [Conditional] attribute. The message reads: "Conditional member 'MethodName' cannot have an out parameter".
In C#, the [Conditional("SYMBOL")] attribute tells the compiler: "If SYMBOL is not defined, delete every call to this method from the compiled code."
However, an out parameter imposes a strict contract: the method must assign a value to that parameter before returning. If the compiler removes the method call because the symbol isn't defined, the assignment never happens. This leaves the variable uninitialized, violating C#'s definite assignment rules. Therefore, C# forbids declaring a Conditional method with out parameters.
This guide explains the conflict and provides safer alternatives.
Understanding the Conflict
To understand why this is an error, consider what happens when the conditional symbol is missing.
- The Code:
bool success; TryLog(out success); - The Contract: C# relies on
TryLogto setsuccessto true or false. - The Attribute:
[Conditional("DEBUG")]removes the lineTryLog(out success);from the binary if "DEBUG" is missing. - The Result: The variable
successis declared but never assigned a value. Any subsequent code usingsuccesswould crash or behave unpredictably.
Because the compiler cannot guarantee the method will run, it cannot guarantee the out variable will be assigned.
Scenario: The Invalid Definition
This error usually occurs when developers try to create a debug-only method that returns status information via an out parameter.
Example of error:
using System.Diagnostics;
public class DebuggerHelper
{
// ⛔️ Error CS0685: Conditional member 'GetStatus' cannot have an out parameter.
// If "DEBUG" is not defined, this method call is stripped.
// The caller would be left with an unassigned 'status' variable.
[Conditional("DEBUG")]
public static void GetStatus(out string status)
{
status = "System is running...";
}
}
public class Program
{
static void Main()
{
string currentStatus; // Uninitialized
// If DEBUG is missing, this line vanishes.
// 'currentStatus' remains uninitialized.
DebuggerHelper.GetStatus(out currentStatus);
// Compiler error: Use of unassigned local variable 'currentStatus'
System.Console.WriteLine(currentStatus);
}
}
Solution 1: Use ref Instead of out
Unlike out, a ref parameter must be initialized before being passed to the method. This satisfies the safety requirement: even if the method call is removed by the compiler, the variable still holds its initial value.
Solution: change the parameter to ref and initialize the variable at the call site.
using System.Diagnostics;
public class DebuggerHelper
{
// ✅ Correct: 'ref' allows the method to be conditional.
// If the method is removed, 'status' keeps its original value.
[Conditional("DEBUG")]
public static void GetStatus(ref string status)
{
status = "System is running...";
}
}
public class Program
{
static void Main()
{
// 1. Initialize the variable first
string currentStatus = "Unknown";
// 2. Pass by ref
DebuggerHelper.GetStatus(ref currentStatus);
// This works regardless of whether DEBUG is defined.
System.Console.WriteLine(currentStatus);
}
}
Solution 2: Use Preprocessor Directives (#if)
If you specifically need out semantics (you don't want to initialize a dummy value beforehand), you cannot use the [Conditional] attribute. Instead, you must wrap both the definition and the call in #if blocks.
This ensures that if the method disappears, the code calling it (and the variable usage) disappears too, maintaining logic consistency.
Solution:
public class DebuggerHelper
{
// ✅ Correct: No attribute. We control compilation manually.
#if DEBUG
public static void GetStatus(out string status)
{
status = "System is running...";
}
#endif
}
public class Program
{
static void Main()
{
#if DEBUG
// This entire block exists only in Debug mode
string currentStatus;
DebuggerHelper.GetStatus(out currentStatus);
System.Console.WriteLine(currentStatus);
#endif
}
}
While Solution 1 (ref) is cleaner to read, Solution 2 (#if) allows you to completely strip the variable declaration itself from the Release build, which might be slightly more memory efficient.
Conclusion
CS0685 ensures variable assignment safety.
- Understand the Constraint: If a method might vanish (due to
[Conditional]), it cannot be responsible for initializing variables (out). - Use
ref: This is the standard fix. Initialize the variable yourself before passing it. - Use
#if: If you must useout, wrap the logic in preprocessor directives instead of using attributes.