Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance for extension methods

How does inheritance work with extension methods in C#.

Say you have an interfaces IA, IB : IA and IC, and a class Foo : IB, IC, now one defines extension methods:

public static class Extensions {

    public static void Bar (this IA instance) {
        //Some code
    }

    public static void Bar (this IB instance) {
        //Some code
    }

    public static void Bar (this IC instance) {
        //Some code
    }

    public static void Bar (this Foo instance) {
        //Some code
    }

}

How does a compiler determines the behavior of Foo.Bar()? Based on empirical tests, the compiler always selects the most specific instance (like a normal call) and without using dynamical binding (since the this annotation) is more "syntactical" sugar I suppose...

In case two or more classes define a method from different branches in the inheritance hierarchy, the call is ambiguous. Is there a way to define priority of one method over another in such cases?

Are the claims above correct?

like image 767
Willem Van Onsem Avatar asked Jul 18 '14 02:07

Willem Van Onsem


1 Answers

Inheritance does matter, but what matters even more is actually the namespace, from the C# spec:

if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation.

The exact process and example can be found in the C# spec, 7.6.5.2 Extension method invocations. The resolution process (where C is the set of possible type resolutions, and M the set of extension methods):

The search for C proceeds as follows:
• Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:

o If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.

o If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.

• If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.

• Otherwise, overload resolution is applied to the candidate set as described in (§7.5.3). If no single best method is found, a compile-time error occurs.

• C is the type within which the best method is declared as an extension method. Using C as a target, the method call is then processed as a static method invocation (§7.5.4).

Which, if I understand it correctly, means it picks the best extension method in the closest namespace at compile time. It is very important to understand that there is no dynamic invocation going on, the resolution is done statically (ie at compiletime).

like image 169
flindeberg Avatar answered Sep 27 '22 19:09

flindeberg