Reputation: 39085
Consider the following program:
class A
{
public static void Foo()
{
}
}
static class Ext
{
public static void Foo(this A a)
{
}
}
class Program
{
static void Main(string[] args)
{
var a = new A();
a.Foo();
}
}
This fails to compile, with the error:
Member 'Test.A.Foo()' cannot be accessed with an instance reference; qualify it with a type name instead
Why is the compiler ignoring the extension method?
Upvotes: 10
Views: 1838
Reputation: 2458
What you are trying to do isn't allowed. The C# MSDN Extension Method Article specifically states that:
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.
Thank goodness it isn't allowed as that would just be awful to have to maintain.
EDIT: So people are saying that static methods aren't instance methods, which is correct. But try doing this:
class A
{
public static void Foo() {}
public void Foo() {}
}
That won't compile either because of a name ambiguity. That is exactly what would happen if you were allowed to use the extension method. It would introduce the exact same ambiguity. Now, given that one method is static and one is instance, should that mean that there is no ambiguity, perhaps. But at the current state it does introduce ambiguity which is yet another reason why it wouldn't be allowed.
Edit #2: From a comment @ErenErsonmez made:
However, as long as the extension method doesn't have the same signature as an instance method, I don't understand how it could ever cause ambiguity with a static method
If you change the signature of the extension method it will definitely work. So the following will work:
class A
{
public static void Foo() { }
}
static class Ext
{
public static void Foo(this A me, int i)
{ }
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Foo(10);
Console.ReadLine();
}
}
So it looks more like the issue is an ambiguity one and not that there can't ever be an extension method of the same name as a method that already exists.
Upvotes: 5
Reputation: 160862
The problem is overload resolution: The static method Foo()
is a candidate, it is applicable - just choosing it as best match will cause an error - which is exactly what happens. Extension methods are only candidates for overload resolution after all other candidates have been considered. In the case of OPs problem case the extension method will not even have been considered before the error occurs.
Upvotes: 3
Reputation: 67075
It appears from this MSDN article that this is due to security concerns.
I have often heard the concern that extension methods can be used to hijack or subvert the intended behavior of existing methods. Visual Basic addresses this by ensuring that, wherever possible, an instance method is preferable over an extension method.
The language allows extension methods to be used to create overloads for existing instance methods with different signatures. This allows extension methods to be used to create overloads, while preventing the existing instance method from being overridden. If an extension method exists with the same signature as an instance method, the shadowing rules that are built into the compiler will prefer the instance method, therefore eliminating the possibility of an extension method overriding existing base class instance functionality
This is VB focused (and instance focused), but still, the general idea is there. Basically, the extension method takes the lowest precedence so that methods cannot be hijacked, and since the class already has a method signature for what you are trying to do, that takes precedence and throws the standard extension method error (when trying to call from an instance object). You can never have two methods with the same signature, and that is what you are asking to be attempted here essentially...and allowing it would be a security concern as explained above already.
Then, add the confusion that will be created by this, and it is just a bad idea to allow it.
Upvotes: 3