Taco
Taco

Reputation: 2923

Accessing extension method within extended type?

I've been refactoring some old code lately and a lot of methods are useful as extension methods to foundational types such as double, float, int, string, etc. However, as I pitter-patted along making great progress, a thought occurred to me. There are multiple ways to access an extension method. Let's create a container class called Extensions and add a basic extension method (at first), and a dummy class we shall call Dummy with a simple method that utilizes our extension method called DoIt.

public static class Extensions {
    public static double ToRadians(this double degrees) => degrees * Math.PI / 180.0;
}
public class Dummy {
    public void DoIt() {
        double radians = Extensions.ToRadians(45.0);
        double degrees = 90.0;
        radians = degrees.ToRadians();
    }
}

Not the most elegant example, but it demonstrates the widely known access to extension methods. Now lets create an idiotic and pointless extension called WasteOfTime for our Dummy class, but within the Extensions class.

I'm not to sure why you would do this, but for the sake of the question, let's do it!

public static class Extensions {
    ...
    public static void WasteOfTime(this Dummy dummy) { }
    ...
}

Alright, now we have this perfect little method that should have just been placed in the Dummy class. Well, since extension methods work off of instances of types, you should be able to call WasteOfTime from the Dummy class' special method called DoIt.

public void DoIt() {
    ...
    WasteOfTime();
    ...
}

Oh, but wait, you can't do that! The method couldn't be found! Let's qualify it with the this keyword!

this.WasteOfTime();

That's better, it compiles! It works! It is a waste of time! Cool!


Important Note

I would NOT consider actually doing this, but out of curiosity I gave it a try. If you can give a valid example as to why this would ever be a good idea, feel free to share, but I believe it is one of those; what were you thinking types of implementations.


The Question

Why did I have to qualify the extension method since modern compilers remove the need for qualifying fields, properties, and methods with the this keyword?

The only thing I can think of is that the extension method is technically static to the base class.

Upvotes: 1

Views: 214

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499830

Firstly, I'll note that there are perfectly good reasons to call extension methods on this. For example, you might be writing a collection class and want to use LINQ within it. Nothing wrong with that. Now, in terms of the question:

Why did I have to qualify the extension method since modern compilers remove the need for qualifying fields, properties, and methods with the this keyword?

It's not a matter of the modernity of the compiler - it's about what the language specification says. From ECMA-334, section 12.7.6.3:

In a method invocation (§12.6.6.2) of one of the forms

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )

if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. If expr or any of the args has compile-time type dynamic, extension methods will not apply.

A method call of the form Method() is not in one of those forms, as there's no expr.

So the compiler's just obeying the rules of the specification. As for why it's designed that way, that's slightly different. I don't know the details of this (although I can see if they're in one of the annotated versions of the spec) but I suspect that the fact that Foo() can either refer to an instance method or a static method in the current class or any of the base classes makes the whole thing a little trickier. (As of C# 6 it could also be a static method in any of the methods imported by a using static directive, mind you...)

Upvotes: 3

Related Questions