Skip to main content

How to Resolve Error "CS0629: Conditional member cannot implement interface member" in C#

The Compiler Error CS0629 is a contract violation error. The message reads: "Conditional member 'Member' cannot implement interface member 'InterfaceMember' in type 'Type'".

In C#, an Interface defines a strict contract: "Any class implementing me must provide this method, and it must be callable." The [Conditional] attribute, however, tells the compiler: "Ignore calls to this method unless a specific symbol (like DEBUG) is defined."

These two concepts contradict each other. If a method is part of an interface, it must always be available to be called via that interface. The compiler cannot selectively omit calls when the method is accessed through the interface (polymorphism), so it forbids applying [Conditional] to interface implementations.

Understanding the Conflict

When you apply [Conditional("DEBUG")] to a method, the method itself remains in the compiled DLL, but the compiler removes all calls to that method from the client code if DEBUG is not defined.

However, Interface calls are often dynamic (virtual dispatch).

ILogger logger = new MyLogger();
logger.Log("Test");

The compiler compiling the code above sees ILogger.Log. It does not see MyLogger.Log. Since ILogger does not have the [Conditional] attribute, the compiler generates the call. If MyLogger.Log implies "do not call me," the runtime behavior becomes inconsistent with the interface contract. Therefore, C# forbids this combination.

Scenario: Marking Implementation as Conditional

This commonly happens when implementing logging or diagnostic interfaces where you only want the logic to run during development.

Example of error:

using System.Diagnostics;

public interface ILogger
{
void Log(string message);
}

public class ConsoleLogger : ILogger
{
// ⛔️ Error CS0629: Conditional member 'Log' cannot implement interface member 'ILogger.Log'
// The interface requires 'Log' to be a standard, callable method.
[Conditional("DEBUG")]
public void Log(string message)
{
System.Console.WriteLine(message);
}
}

Solution: Use Preprocessor Directives Inside the Method

To achieve the goal of "only run this code in DEBUG mode" while satisfying the interface contract, you must keep the method signature standard but wrap the body of the method in preprocessor directives (#if / #endif).

This ensures the method always exists and satisfies the interface, but it does nothing (is empty) when compiled in Release mode.

Solution

using System.Diagnostics;

public interface ILogger
{
void Log(string message);
}

public class ConsoleLogger : ILogger
{
// ✅ Correct: The method signature is permanent and valid.
public void Log(string message)
{
// The implementation details are conditional.
#if DEBUG
System.Console.WriteLine(message);
#endif
}
}

Alternative Solution: Conditional Helper Method

If you want to keep the clean [Conditional] attribute syntax for internal usage, you can have the interface implementation delegate to a private conditional method.

public class ConsoleLogger : ILogger
{
// The Interface Implementation (Must be standard)
public void Log(string message)
{
LogInternal(message);
}

// The Logic (Can be conditional)
[Conditional("DEBUG")]
private void LogInternal(string message)
{
System.Console.WriteLine(message);
}
}

In this scenario:

  • Debug Mode: Log calls LogInternal, which prints the message.
  • Release Mode: Log calls LogInternal, but the compiler strips that call out, leaving Log as an empty method.

Conclusion

CS0629 ensures that interface contracts are reliable.

  1. Check Attributes: Remove [Conditional(...)] from any method that implements an interface member.
  2. Move Logic: Place the #if SYMBOL directives inside the method body.
  3. Delegate: Alternatively, make the interface method call a private method that is marked [Conditional].