How to Resolve Warning "CS0467: Ambiguity between method 'method' and non-method 'non-method'" in C#
The Compiler Warning CS0467 is a Resolution Ambiguity warning. The message reads: "Ambiguity between method 'MethodName' and non-method 'PropertyName'. Using method group."
This warning occurs when a type (usually an interface) inherits members from two different sources, and those members share the exact same name but are of different kinds (e.g., one is a Method and the other is a Property or Field). When you attempt to access this member, the compiler is unsure which one you intend to use. To proceed, the compiler creates a specific rule: it assumes you meant the Method.
This guide explains how this collision happens and how to access the specific member you actually want.
Understanding the Member Collision
In C#, it is valid for two different interfaces to have a member with the same name.
InterfaceAhasvoid Run();(Method)InterfaceBhasint Run { get; }(Property)
If you create InterfaceC that inherits from both, InterfaceC now contains two members named Run.
When you write myObj.Run, the compiler has to perform a lookup. Because there is a conflict, C# generates CS0467 and defaults to selecting the Method. If you actually wanted the Property, your code will likely fail to compile or behave incorrectly.
Scenario: Interface Aggregation Conflict
This situation is most common when combining interfaces from different libraries or legacy code.
Setup
// Interface with a Method
public interface IRunnable
{
void DoWork();
}
// Interface with a Property of the same name
public interface IJobStatus
{
int DoWork { get; }
}
// Aggregated Interface
public interface IComplexJob : IRunnable, IJobStatus
{
// Inherits both 'void DoWork()' and 'int DoWork'
}
Example of warning
Attempting to access the member directly on the combined interface.
public class Program
{
static void Main(string[] args)
{
IComplexJob job = GetJob();
// ⛔️ Warning CS0467: Ambiguity between method 'IRunnable.DoWork()'
// and non-method 'IJobStatus.DoWork'. Using method group.
// The compiler assumes you mean the METHOD.
// If you try to use it like a method, it works (with a warning):
job.DoWork();
// If you try to use it like a property, it fails:
// int status = job.DoWork; // Error: Cannot convert method group to int
}
static IComplexJob GetJob() => null;
}
The compiler's choice to "Use method group" allows method calls to succeed, but it effectively makes the Property inaccessible via the combined interface variable.
Solution 1: Explicit Casting (Resolving Ambiguity)
To tell the compiler exactly which member you want, you must cast the object to the specific interface that defined that member. This removes the ambiguity because that specific interface only has one member with that name.
Accessing the Method
public void Execute(IComplexJob job)
{
// ✅ Correct: Cast to IRunnable to strictly access the Method
((IRunnable)job).DoWork();
}
Accessing the Property
public void CheckStatus(IComplexJob job)
{
// ✅ Correct: Cast to IJobStatus to strictly access the Property
int status = ((IJobStatus)job).DoWork;
System.Console.WriteLine($"Status: {status}");
}
Solution 2: Renaming Members (Design Fix)
If you have control over the interface definitions (i.e., you are not consuming third-party DLLs), the best solution is to follow .NET naming conventions to avoid the collision entirely.
Typically, methods are Verbs and properties are Nouns.
Solution: rename the property to be more descriptive.
public interface IRunnable
{
// Verb
void DoWork();
}
public interface IJobStatus
{
// ✅ Correct: Noun (Renamed from DoWork)
int WorkStatus { get; }
}
public interface IComplexJob : IRunnable, IJobStatus { }
Now, job.DoWork() calls the method, and job.WorkStatus reads the property. No ambiguity exists.
Conclusion
CS0467 is the compiler making a "best guess" to resolve a naming conflict between different member types.
- Understand the Default: The compiler will always pick the Method over the Property/Field when this conflict occurs.
- Use Casting: To access the hidden Property, cast the object to the specific interface that defines it (e.g.,
((IPropertyInterface)obj).Prop). - Refactor: If possible, rename members to avoid having methods and properties share the exact same identifier.