C# Extension method specificity

clmcgov 21 Reputation points
2024-09-04T22:11:43.5866667+00:00

Suppose I have an interface and a class implementing that interface:

public interface IFoo {}
public class Foo : IFoo {}

Now suppose I have defined an overloaded extension method on both the class and the interface:

public static class FooExtensions 
{
  public static void ExtensionMethod(this IFoo foo) 
  {
    Console.WriteLine("bar");
  }

  public static void ExtensionMethod(this Foo foo) 
  {
    Console.WriteLine("baz");
  }
}

Now suppose I call ExtensionMethod like so:

const Foo foo = new();
foo.ExtensionMethod();

What should be printed to the terminal? In my experience, it's always "baz". This seems intuitive, but is it a coincidence, or is it the rule?

Thanks!

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,808 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,858 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jiale Xue - MSFT 44,751 Reputation points Microsoft Vendor
    2024-09-05T02:42:13.6833333+00:00

    Hi @clmcgov , Welcome to Microsoft Q&A,

    Calling foo.ExtensionMethod() will print "baz". This is the rule in C#, not just a coincidence.

    Extension methods are provided through static classes, but they are called as if they were instance methods of an object. When the C# compiler processes extension methods, it resolves them according to the following rules:

    Compile-time type: The compiler first looks at the compile-time type of the object on which the method is called, not the runtime type. Most specific extension method first: If there are multiple extension methods whose signatures match the call, the compiler chooses the most specific type. In other words, if there are two extension methods, one for an interface type (IFoo) and another for a concrete type (Foo), the compiler chooses the one that best matches the concrete type. Explain the code

    const Foo foo = new();
    foo.ExtensionMethod();
    

    In this line of code, foo is of type Foo, and the compiler first looks for an extension method that matches the type of Foo. The extension method ExtensionMethod(this Foo foo) is the most specific match, so it is selected, printing "baz". If you declare foo as type IFoo:

    const IFoo foo = new Foo();
    foo.ExtensionMethod();
    

    Here, foo is of type IFoo, and the compiler selects the extension method ExtensionMethod(this IFoo foo), so it prints "bar".

    Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.