Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

117
Views
Are extension methods for interfaces treated as lower priority than less specific ones?

I have the following extensions class:

public static class MatcherExtensions
{
    public static ExecMatcher<T1, T2> Match<T1, T2>(this Tuple<T1, T2> item)
    {
        return new ExecMatcher<T1, T2>(item.Item1, item.Item2);
    }

    public static ExecMatcher<T1, T2> Match<T1, T2>(this ITupleMatchable<T1, T2> item)
    {
        var tuple = item.PropertiesToMatch;
        return new ExecMatcher<T1, T2>(tuple.Item1, tuple.Item2);
    }

    public static ExecMatcher<T> Match<T>(this T item) { return new ExecMatcher<T>(item); }
}

If I create a tuple and invoke Match(), it correctly uses the first extension method:

var tuple = Tuple.Create(1, "a");
tuple.Match().With(1, "a")...   // compiles just fine.

If I create a int and invoke Match(), it correctly uses the last extension method:

var one = 1;
one.Match().With(1)... // compiles just fine.

However if I create SomeClass, which implements ITupleMatchable<int, string> and try and match on it, the compiler still chooses the third extension method, rather than the second one, despite the latter being a more specific match:

var obj = new SomeClass(1, "a");
obj.Match().With(1, "a")... // won't compile.

Based on Eric Lippert's answer to a similar question, I have worked around this by putting the third extension method into its own class within a subdirectory, thus creating a longer namespace and so more "distance" between it and the calling code than for the version specific to ITupleMatchable<T1, T2>. This feels like a hack to me though. Is there a neater way of resolving this?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

If you simply cast new SomeClass(1, "a") to ITupleMatchable<int, string>, it will work fine:

var obj = (ITupleMatchable<int, string>)new SomeClass(1, "a");
obj.Match().With(1, "a");

Remember that your obj variable otherwise has a compile-time type of SomeClass. The compiler can "more easily" match the actual class to the third extension method (which is compatible with any type), than it can by having to look at the interface implementations of SomeClass and then matching it to e.g. the second extension method.

But if you provide the this parameter as the actual interface type, then the second extension method is a better fit, because it's exactly the type the method is looking for, rather than being the broader "any type". I.e. it's a more specific declaration, and so is "better".

Note that once the candidate set of extension methods is found (via rules relating to the namespace, etc.), the actual method is determined using normal overload resolution. I.e. having determined that at least one method in your MatcherExtensions class is an eligible extension method, the compiler then goes with the normal overload resolution rules to pick among those. You can find those rules in the C# 5.0 specification, section 7.5.3.

Briefly though: before applying the overload resolution rules (indeed, in order to determine which methods are even eligible), note that the compiler has already decided the generic type parameters. So, as it evaluates the overload resolution, it is looking at Match(SomeClass item) and Match(ITupleMatchable<int, string> item). Hopefully once you consider that, you'll see why, if the variable has the type SomeClass, the compiler picks your third extension preferentially over the second, and vice a versa if the type is ITupleMatchable<int, string>.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!