90

I have created an extension method for an ASP.NET MVC ViewPage, e.g:

public static class ViewExtensions
{
    public static string Method<T>(this ViewPage<T> page) where T : class
    {
        return "something";
    }
}

When calling this method from a View (deriving from ViewPage), I get the error "CS0103: The name 'Method' does not exist in the current context" unless I use the this keyword to call it:

<%: Method() %> <!-- gives error CS0103 -->
<%: this.Method() %> <!-- works -->

Why is the this keyword required? Or does it work without it, but I'm missing something?

(I think there must be a duplicate of this question, but I was not able find one)

Update:

As Ben Robinson says, the syntax to call extension methods is just compiler sugar. Then why can't the compiler automatically check the for extension methods of the current type's base types without requiring the this keyword?

Community
  • 1
  • 1
M4N
  • 94,805
  • 45
  • 217
  • 260
  • @M4N - This looks like the possible duplicate you were after: [Why can't I call OrderBy in a class that extends List?](http://stackoverflow.com/questions/2144034/why-cant-i-call-orderby-in-a-class-that-extends-list) – djdd87 Aug 18 '10 at 10:23
  • 1
    @GenericTypeTea: yes it's a similar question. But I'm not asking how to call the extension method (I *know* I have to add the `this` keyword), but I'm asking why the `this` keyword is required. I updated my question. – M4N Aug 18 '10 at 10:29
  • @M4N - Good point, they say it has to be done, but the answers don't really give a good enough explanation as to why. – djdd87 Aug 18 '10 at 10:41
  • On instance methods, 'this' is *implicitly* passed to the method. By calling Method() rather than this.Method() or Method(this), you're not telling the compiler what to pass to the method. – Alex Humphrey Aug 18 '10 at 11:17
  • @Alex. Technically i imagine it would be possible for the compiler to infer "this" in the context of calling Method(), however i think that this would have been a bad design choice and make code less readable. – Ben Robinson Aug 18 '10 at 13:06
  • @Ben Robinson - agreed - I kind of turned my comment into an answer which goes over that - the compiler would have to error if it was called from a static context though. – Alex Humphrey Aug 18 '10 at 13:35
  • Eric Gunnerson: "Every feature starts out in the hole by 100 points, which means that it has to have a significant net positive effect on the overall package for it to make it into the language." Before you ask why a feature is missing, you need to provide a compelling scenario for why it would be useful. – Brian Aug 19 '10 at 13:36

6 Answers6

60

A couple points:

First off, the proposed feature (implicit "this." on an extension method call) is unnecessary. Extension methods were necessary for LINQ query comprehensions to work the way we wanted; the receiver is always stated in the query so it is not necessary to support implicit this to make LINQ work.

Second, the feature works against the more general design of extension methods: namely, that extension methods allow you to extend a type that you cannot extend yourself, either because it is an interface and you don't know the implementation, or because you do know the implementation but do not have the source code.

If you are in the scenario where you are using an extension method for a type within that type then you do have access to the source code. Why are you using an extension method in the first place then? You can write an instance method yourself if you have access to the source code of the extended type, and then you don't have to use an extension method at all! Your implementation can then take advantage of having access to the private state of the object, which extension methods cannot.

Making it easier to use extension methods from within a type that you have access to is encouraging the use of extension methods over instance methods. Extension methods are great, but it is usually better to use an instance method if you have one.

Given those two points, the burden no longer falls on the language designer to explain why the feature does not exist. It now falls on you to explain why it should. Features have enormous costs associated with them. This feature is not necessary and works against the stated design goals of extension methods; why should we take on the cost of implementing it? Explain what compelling, important scenario is enabled by this feature and we'll consider implementing it in the future. I don't see any compelling, important scenario that justifies it, but perhaps there is one that I've missed.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 19
    Thanks for that answer! Two points: 1: I was not asking for that feature to be implemented, just for an explanation, why it isn't there / why `this` is required. 2: Why do I call an extension method from the extended type? In the example given, I'm adding some convenience methods to the base class (ViewPage) and I'm calling it from derived classes. This eliminates the need of creating a common base class for all my views. BTW: I agree that using an extension method from within the extended type is awkward, but again see the example with MVC ViewPage. – M4N Aug 18 '10 at 15:25
  • 1
    I don't think the reason that extension methods were needed for LINQ is a good justification, as its not the only reason why one might use them, now that they exist. This doesn't stop me agreeing with the rest of the answer that implicit this is unnecessary. I can see one use for implicit this (implementing an interface or derived class for which an extension method already exists), but even here that extension methods "work from the outside" is reflected is a good thing IMO. – Jon Hanna Sep 24 '10 at 14:45
  • 5
    @M4N: that's exactly my situation too: I want to extend the UserControl method & have that extension available to all my UserControls, without the explicit 'this'. I know that compiler development isn't a democracy but consider this my vote for an implicit 'this' :-) – Duncan Bayne Jan 21 '11 at 02:40
  • 10
    Hi Eric, granted this isn't a primary scenario. However the general pattern seems to to be 1. You do not have source-edit access to a base class. 2. you want to add some (protected) methods to the base type, which you want to invoke within the bodies of the derived classes. Is there some other mechanism to achieve this? this.MethodName is not that hard to type but it gets annoying after a while... – Gishu Apr 14 '11 at 04:10
  • 3
    *"If you are in the scenario where you are using an extension method for a type within that type then you do have access to the source code..."* - I would point out that, for example, I may want to add an extension method to `System.Object` (in my case, and how I found this post, for a simple event aggregation service). I want *every* object to contain this method, but I have to use an extension method to do so. In this case I do not believe that I am working against the intended use of this feature. That said, using `this` is not a big deal and I'm fine with it, I was just curious. – Ed S. May 25 '11 at 23:10
  • A big scenario where one would want to define an extension method within its own type would be with interfaces (being able to attach other static methods like factories to interfaces would be useful as well). It would also be useful in cases where a non-virtual method should be invokable on a null object with a known compile-time type (e.g. it would be much cleaner to say "someString.IsNullOrEmpty() than "String.IsNullOrEmpty(someString)). Allowing structs to declare extension methods with a "ref this" parameter would let compilers flag mutating methods used in read-only contexts. – supercat Nov 18 '11 at 00:12
  • I came across this when trying to add a protected member to `Windows.Ui.Xaml.Page` for easier navigating, which seems to be the scenario as also described by @Gishu. – Jeroen Vannevel Dec 02 '14 at 16:14
  • 9
    I think the scenario of adding an extension method to a base class (to which you don't have the source for) is a valid one. In that case it would've been nice to be able to call the method without "this". BTW this may be solved in the next c# version with "static imports". – lysergic-acid May 13 '15 at 10:44
  • 5
    One valid reason to use extension methods from within the class you are extending is when you have multiple types which implement an interface. E.g. you have two classes which implement `ICrossProductable`, and you define an extension method on that interface called `GetProduct`. Very simple example, but I often find this useful. It's not the best approach in all cases though. – Ian Newson Feb 29 '16 at 14:43
  • One scenario that would potentially useful is to add an extension method to `object` such as `public static void Log(this object, string message)`. You have to call that with `this.Log("msg");` you can't implicitly call it. – stevieg Sep 06 '16 at 23:54
  • 1
    While wanting to avoid too much me-too-ism, this good stack overflow answer discusses exactly my use case (http://stackoverflow.com/questions/20139621/how-do-i-return-notfound-ihttpactionresult-with-an-error-message-or-exception), which is a specific useful example where it is useful to add exension methods to a class you are inheriting from. As they say there (correctly, I would suggest, in this context) "If you used a custom ... base class (instead of directly inheriting ...), you could also eliminate the "this." part (which is unfortunately required when calling an extension method)". – MikeBeaton Sep 27 '16 at 14:26
  • 2
    @bmju: I encourage you to make that case to the C# language designers in the Roslyn github forum. I haven't worked at Microsoft since 2012. – Eric Lippert Sep 27 '16 at 15:47
  • @lysergic-acid I fail to see how static imports can help here. – Steven Jeuris Mar 03 '17 at 13:57
10

Without it the compiler just sees it as a static method in a static class which takes page as it's first parameter. i.e.

// without 'this'
string s = ViewExtensions.Method(page);

vs.

// with 'this'
string s = page.Method();
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
6

On instance methods, 'this' is implicitly passed to each method transparently, so you can access all the members it provides.

Extension methods are static. By calling Method() rather than this.Method() or Method(this), you're not telling the compiler what to pass to the method.

You might say 'why doesn't it just realise what the calling object is and pass that as a parameter?'

The answer is that extension methods are static and can be called from a static context, where there is no 'this'.

I guess they could check for that during compilation, but to be honest, it's probably a lot of work for extremely little payoff. And to be honest, I see little benefit in taking away some of the explicitness of extension method calls. The fact that they can be mistaken for instance methods means that they can be quite unintuitive at times (NullReferenceExceptions not being thrown for example). I sometimes think that they should have introduced a new 'pipe-forward' style operator for extension methods.

Alex Humphrey
  • 6,099
  • 4
  • 26
  • 41
  • So it seems like they made a really bad design choice of having it be able to be called from a static context then, as I don't see why anyone ever would. – AustinWBryan Sep 30 '18 at 08:32
4

It's important to note that there are differences between extension methods and regular methods. I think you've just come across one of them.

I'll give you an example of another difference: It's fairly easy to call an extension method on a null object reference. Fortunately, this is much more difficult to do with regular methods. (But it can be done. IIRC, Jon Skeet demonstrated how to do this by manipulating CIL code.)

static void ExtensionMethod(this object obj) { ... }

object nullObj = null;
nullObj.ExtensionMethod();  // will succeed without a NullReferenceException!

That being said, I agree that it seems a little unlogical that this is required to call the extension method. After all, an extension method should ideally "feel" and behave just like a normal one.

But in reality, extension methods are more like syntactic sugar added on top of the existing language than an early core feature that fits nicely into the language in all respects.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • in Boo language you can invoke Extension method or property directly on null i.e. null.Do(). – Sergey Mirvoda Aug 18 '10 at 10:28
  • 1
    @Sergey: Sounds dangerous... :) Makes me curious how Boo knows the (implied) type of `null`? Could be just about any reference type, how does it know what methods are available on `null`? – stakx - no longer contributing Aug 18 '10 at 10:31
  • 1
    There may be a good reason to be able to call an extension method with a null reference. – Dave Van den Eynde Aug 18 '10 at 12:55
  • @DaveVandenEynde: IMHO, it was a mistake for .net not to define an attribute for non-virtual methods that would require that compilers invoke them with non-virtual calls. Some immutable class types like `String` logically behave as values, and could have a sensible default when null (e.g. .net could consistently regard a null reference of static type `string` as an empty string, rather than doing so only sporadically). Having to use static methods for things like `if (!String.IsNullOrEmpty(stringVar))` is simply hideous. – supercat Jul 10 '12 at 21:01
  • 1
    @supercat Yes, hideous. You can also do string.IsNullOrEmpty(). Much prettier. – Dave Van den Eynde Jul 12 '12 at 10:19
  • @DaveVandenEynde: Do you mean using the lowercase `string` reserved word in place of the uppercase `String` type identifier, but still using a static method (adding the string to test in the parenthesis), or do you mean using an extension method (i.e. replacing your text "string" with the string to test)? – supercat Jul 12 '12 at 14:46
  • @supercat I was being sarcastic, don't worry. – Dave Van den Eynde Jul 16 '12 at 08:50
1

Because the extension method does not exist with the ViewPage class. You need to tell the compiler what you are calling the extension method on. Remember this.Method() is just compiler sugar for ViewExtensions.Method(this). It is the same way you can't just call an extention method within the middle of any class by the method name.

Ben Robinson
  • 21,601
  • 5
  • 62
  • 79
  • 1
    This makes sense (somehow). But if it's compiler sugar, then why can't the compiler check for extension methods without the `this` keyword? – M4N Aug 18 '10 at 10:23
  • Looks like an oversight to me. As you said - the compiler could see the method does not exist, then check extensions for availability. – TomTom Aug 18 '10 at 10:26
  • Yeah arguably this could work. I would suspect it is a specific design decision to make the code more readable. If you could simply call ExtensionMethod() within a class it might be a bit confusing to someone reading the code if that class doesn't contain that method but with this.ExtensionMethod() at least it is consistent with using MyInstance.ExtentionMethod() – Ben Robinson Aug 18 '10 at 10:48
  • I think that this.Method() is more like syntactic sugar for ViewExtensions.Method(this). – Alex Humphrey Aug 18 '10 at 11:12
1

I am working on a fluent API and ran into the same issue. Even though I have access to the class I'm extending I still wanted the logic of each of the fluent methods to be in their own files. The "this" keyword was very unintuitive, users kept thinking the method was missing. What I did was make my class a partial class that implemented the methods I needed instead of using extension methods. I saw no mention of partials in the answers. If you have this question partials might be a better option.

Reyn
  • 261
  • 1
  • 4
  • 11