Skip to main content

How to Resolve Error "CS0767: Cannot inherit interface with the specified type parameters because it causes method to contain overloads which differ only on ref and out" in C#

The Compiler Error CS0767 is a generic substitution error related to Method Overloading. The message reads: "Cannot inherit interface 'InterfaceName' with the specified type parameters because it causes method 'MethodName' to contain overloads which differ only on ref and out".

In C#, you cannot overload methods based solely on the difference between ref and out. To the Common Language Runtime (CLR), both ref int and out int represent the same thing (a pointer to an integer). While C# treats them differently for definite assignment rules, it forbids defining two methods with the same name where one takes ref T and the other takes out T if T is the same type.

This error occurs when you use Generics to inadvertently create this forbidden scenario by substituting two different generic placeholders with the exact same type.

Understanding the Ref/Out Overload Restriction

In C#, the following overloads are valid:

  • void Method(int x) vs void Method(ref int x) (By-val vs By-ref).
  • void Method(ref int x) vs void Method(ref string x) (Different types).

The following overload is invalid:

  • void Method(ref int x) vs void Method(out int x).

The compiler cannot distinguish these signatures at the binary level. CS0767 happens when an interface defines Method(ref T) and Method(out U), and you implement it as Interface<int, int>, forcing T and U to become the same type, thus creating the illegal overload pair.

Scenario: The Generic Substitution Collision

You have a generic interface designed to handle two different types (T and U). It seems valid when defined because T and U are distinct placeholders. However, the moment you create a class that sets T = int and U = int, the signatures collapse into a conflict.

Example of error

// The interface definition looks fine generically.
// T and U are expected to be different types.
public interface IProcessor<T, U>
{
void Process(ref T data); // Method A
void Process(out U data); // Method B
}

// ⛔️ Error CS0767: Cannot inherit interface 'IProcessor<int, int>'...
// Substituting T=int and U=int results in:
// void Process(ref int data);
// void Process(out int data);
// These two methods cannot coexist in the same class.
public class NumberProcessor : IProcessor<int, int>
{
public void Process(ref int data) { }
public void Process(out int data) { data = 0; }
}

Solution 1: Use Different Types

If the logic permits, ensure that the type arguments provided to the interface are distinct. If T and U are different (e.g., int and double), the overloads are valid because they differ by parameter type.

// ✅ Correct: 'ref int' differs from 'out double'.
public class NumberProcessor : IProcessor<int, double>
{
public void Process(ref int data)
{
// ...
}

public void Process(out double data)
{
data = 0.0;
}
}

Solution 2: Rename Methods in the Interface

If you fundamentally need T and U to be the same type (e.g., both int), then your interface design is flawed because it relies on overloads that are not stable. You must rename the methods to be distinct regardless of the types used.

Refactored Interface:

public interface IProcessor<T, U>
{
// ✅ Correct: Distinct names prevent collisions regardless of T and U types.
void ProcessInput(ref T data);
void ProcessOutput(out U data);
}

// Now valid even if T and U are both int
public class NumberProcessor : IProcessor<int, int>
{
public void ProcessInput(ref int data) { }
public void ProcessOutput(out int data) { data = 0; }
}
note

Why does this happen? This is a safeguard. If the compiler allowed this, calling Process(variable) would be ambiguous. The compiler wouldn't know if you intended to pass the variable by ref (input/output) or out (output only) if you didn't explicitly type the keyword, and at the binary level, the calls look identical.

Conclusion

CS0767 is a generic constraint enforcement.

  1. Analyze the Interface: Look for methods with the same name where one uses ref T and the other uses out U.
  2. Check the Implementation: Are you setting T and U to the same type (e.g., int)?
  3. Fix: Either change the types so they don't match, or (better) rename the methods in the interface to avoid relying on fragile overloading rules.