Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call an extension method from own class without casting?

I'm trying to call an extension method on my own class, but it fails to compile. Consider the following lines of code:

public interface IHelloWorld
{
}

public static class Extensions
{
    public static string HelloWorld(this IHelloWorld ext)
    {
        return "Hello world!";
    }
}

public class Test : IHelloWorld
{
    public string SaySomething()
    {
        return HelloWorld();
    }
}

Basically I'm extending on the interface. I keep getting this error:

The name 'HelloWorld' does not exist in the current context

Can anybody explains this to me? When I do a cast all seems well:

return ((Test)this).HelloWorld();

Any explanations?

like image 484
Kees C. Bakker Avatar asked Mar 19 '12 14:03

Kees C. Bakker


People also ask

How do you call an extension method?

To define and call the extension methodDefine a static class to contain the extension method. The class must be visible to client code. For more information about accessibility rules, see Access Modifiers. Implement the extension method as a static method with at least the same visibility as the containing class.

Can we define extension method for a class which itself?

You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself.

Can you add extension methods to an existing static class?

No. Extension methods require an instance of an object.

Can we add extension method to sealed class?

You can also add new methods in the sealed class also using an extension method concept. It cannot apply to fields, properties, or events.


3 Answers

The cast isn't necessary - the this part is. So this works fine:

return this.HelloWorld();

Section 7.6.5.2 explicitly talks about method invocations of the form

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

This invocation:

HelloWorld()

isn't of that form, as there's no expression involved.

It's not immediately clear to me why the language was designed that way (i.e. why the "implicit this" was excluded) and maybe Eric Lippert will add an answer to that effect later. (The answer may well be along the lines of "because it would have taken a long time to spec, implement and test, for relatively little benefit.") However, this answer at least shows that the C# compiler is sticking to the spec...

like image 134
Jon Skeet Avatar answered Nov 02 '22 14:11

Jon Skeet


this.HelloWorld(); works with no casting.

Remember how Extension methods work:

You use an object and compiler would know the type then it could resolve it to the extension method. If no object is used, then it would not be able to resolve it.

like image 22
Aliostad Avatar answered Nov 02 '22 14:11

Aliostad


Not really an answer, but too long to fit in the comment section...

Let's take the following example, that I think is pretty common:

public class DoubleSet : List<double>
{
    public IEnumerable<double> Square()
    {
        return this.Select( x => x*x );
    }
}

It is a perfectly valid point that the this is not necessary for the compiler to interpret the Select method properly.

However I think that in some ways, imposing the dot notation highlights the fact that we're dealing with an extension method, and that as such, the extension method will only access the members of the current instance through public accessors, even if you're calling it within the private scope of the class.

It makes explicit to the code reader that the extension method will treat the "this" instance as if it didn't know anything of its internal state. And indeed the class of the object is completely unknown to the extension method (as the extension method only knows the interface)

If the code was only:

    public IEnumerable<double> Square()
    {
        return Select( x => x*x );
    }

it would be much less obvious that you're dealing with IEnumerable.Select that is actually calling the IList.GetEnumerator and getting every element one by one to call the x => x*x function.

like image 34
edeboursetty Avatar answered Nov 02 '22 12:11

edeboursetty