Skip to main content

How to Resolve Warning "CS0162: Unreachable code detected" in C#

The Compiler Warning CS0162 is a logic flow warning. The message reads: "Unreachable code detected".

This warning occurs when the C# compiler analyzes your code's control flow and determines that a specific block of code can never be executed under any circumstances. This usually happens because a control flow statement (like return, break, continue, or throw) unconditionally interrupts the execution path before the code in question is reached, or because a condition (like if (false)) effectively blocks entry to a section.

While this is a warning and not an error (your code will still compile), it almost always indicates a bug, redundant logic, or leftover debug code that should be removed.

Understanding Control Flow Analysis​

The compiler traces the execution path of your program from top to bottom. It understands that certain keywords stop the current flow:

  • return: Exits the method immediately.
  • throw: Exits the method immediately (via exception).
  • break / continue: Jumps out of or to the top of a loop.

If you write statements immediately after one of these keywords within the same block scope, the compiler knows those statements are "dead code."

Scenario 1: Code After Return or Throw​

This is the most frequent cause. You might have added a debug return to test something and forgot to remove it, or you misunderstood the flow of a throw statement.

Example of error​

public int Calculate(int a, int b)
{
return a + b;

// ⛔️ Warning CS0162: Unreachable code detected
// The method executed 'return' on the line above.
// It is physically impossible to reach this line.
Console.WriteLine("Calculation finished");
}

Solution: Move or Remove​

If the code is meant to run, move it before the return. If it is old logic, delete it.

public int Calculate(int a, int b)
{
// ✅ Correct: Executed before the method exits
Console.WriteLine("Calculation starting...");

return a + b;
}

Throwing Exceptions​

The same logic applies to exceptions.

public void Process()
{
throw new Exception("Stop here");

// ⛔️ Warning CS0162: Unreachable code detected
int x = 10;
}

Scenario 2: Infinite Loops​

If you create a loop that theoretically runs forever (e.g., while (true) or for (;;)), and that loop does not contain a break or return statement, the compiler assumes that any code written after the loop block is unreachable.

Example of error​

public void RunService()
{
while (true)
{
// Infinite work...
}

// ⛔️ Warning CS0162: Unreachable code detected
// Since the loop condition is always 'true' and there is no 'break',
// the code can never exit the loop to reach this line.
Console.WriteLine("Service Stopped");
}

Solution: Add a Break Condition​

Ensure there is a logical path out of the loop.

public void RunService(bool keepRunning)
{
while (keepRunning)
{
// Work...
if (ShouldStop())
{
break; // ✅ Correct: This allows flow to exit the loop
}
}

// Now reachable
Console.WriteLine("Service Stopped");
}

Scenario 3: Constant Conditions (Dead Blocks)​

If you use an if statement with a condition that is a compile-time constant evaluating to false, the compiler knows the block will never run.

Example of error​

public void Config()
{
// ⛔️ Warning CS0162: Unreachable code detected
if (false)
{
Console.WriteLine("This will never print.");
}

const bool isFeatureEnabled = false;

// ⛔️ Warning CS0162: Since 'isFeatureEnabled' is const,
// the compiler knows this is dead code.
if (isFeatureEnabled)
{
EnableFeature();
}
}

Solution: Use Variables or Remove Code​

If you are temporarily disabling code, commenting it out is often cleaner than using if (false). If the logic depends on configuration, use a standard (non-const) variable or a static readonly field, which is evaluated at runtime.

public class FeatureFlags
{
// ✅ Correct: static readonly is a Runtime check, not Compile-time.
// The compiler assumes the value *could* change (via reflection or init),
// so it does not flag the code as unreachable.
public static readonly bool IsFeatureEnabled = false;
}

public void Config()
{
if (FeatureFlags.IsFeatureEnabled)
{
EnableFeature(); // No warning
}
}
note

Conditional Compilation: If you want to include code only for specific builds (like Debug vs Release), use preprocessor directives instead of if (false).

#if DEBUG
Console.WriteLine("Debug Mode");
#endif

This removes the code from the compiled binary entirely, avoiding CS0162 warnings.

Conclusion​

CS0162 is a helpful "garbage collection" warning for your source code.

  1. Check Returns: Look for code lingering after a return statement.
  2. Check Loops: Ensure your while(true) loops have a break statement.
  3. Check Conditions: Avoid if (false) or const bool = false checks; use static readonly or #if directives instead.