Why can you not invoke extension methods directly? - c#

Can someone explain to me why in the following the 3rd invocation of DoSomething is invalid?
( Error message is "The name 'DoSomething' does not exist in the current context" )
public class A { }
public class B : A
{
public void WhyNotDirect()
{
var a = new A();
a.DoSomething(); // OK
this.DoSomething(); // OK
DoSomething(); // ?? Why Not
}
}
public static class A_Ext
{
public static void DoSomething(this A a)
{
Console.WriteLine("OK");
}
}

Extension methods can be invoked like other static methods.
Change it to A_Ext.DoSomething(this).
If you're asking why it isn't implicitly invoked on this, the answer is that that's the way the spec was written. I would assume that the reason is that calling it without a qualifier would be too misleading.

Because DoSomething takes a parameter.
DoSomething(a) would be legal.
Edit
I read the question a bit wrong here.
Since your calling it a a normal static method, and not a extension method, you need to prefic with the class name.
So A_Ext.DoSomething(a); will work.
If you call it like a normal static method, all the same rules apply.
Your second variant works because B inhetits A, and therefore you still end up calling it as an extension method, but the third does not.
sorry about the first version above that does not work. I'll leave it to keep the comment relevant.

Extension methods are still static methods, not true instance calls. In order for this to work you would need specific context using instance method syntax (from Extension Methods (C# Programming Guide))
In your code you invoke the extension
method with instance method syntax.
However, the intermediate language
(IL) generated by the compiler
translates your code into a call on
the static method. Therefore, the
principle of encapsulation is not
really being violated. In fact,
extension methods cannot access
private variables in the type they are
extending.
So while normally, both syntaxes would work, the second is without explicit context, and it would seem that the IL generated can't obtain the context implicitly.

DoSomething requires an instance of A to do anything, and without a qualifier, the compiler can't see which DoSomething you need to invoke. It doesn't know to check in A_Ext for your method unless you qualify it with this.

Related

Why can't I call an extension method from a base class of the extended type‏?

I'm trying add the ability to lookup elements in a List<KeyValuePair<string,int>> by overriding the indexer.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class MyList : List<KeyValuePair<string, int>>
{
public int this[string key]
{
get
{
return base.Single(item => item.Key == key).Value;
}
}
}
}
For some reason, the compiler is throwing this error:
'System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string,int>>' does not contain a definition for 'Single'.
While it is true that List<T> doesn't have that method, it should be visible because it is an extension method from the System.Linq namespace (which is included). Obviously using this.Single resolves the issue, but why is access via base an error?
Section 7.6.8 of the C# spec says
When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct.
Which might seem to preclude access to extension method via base. However it also says
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
If base.I is just like ((B)this).I then it seems like extension methods should be allowed here.
Can anyone explain the apparent contradiction in these two statements?
Consider this situation:
public class Base
{
public void BaseMethod()
{
}
}
public class Sub : Base
{
public void SubMethod()
{
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base) { }
}
Here are some interesting assertions about this code:
I cannot call the extension method using ExtensionMethod() from neither Base nor Sub.
I cannot call base.ExtensionMethod() from Sub.
I can call the extension method using Extensions.ExtensionMethod(this) from both Sub and Base.
I can call the extension method using this.ExtensionMethod() from both Sub and Base.
Why is this?
I don't have a conclusive answer, partly because there might not be one: as you can read in this thread, you have to add this. if you want to call it in the extension method style.
When you're trying to use an extension method from the type it is in (or - consequently - from a type that is derived from the type used in the extension method), the compiler doesn't realize this and will try to call it as a static method without any arguments.
As the answer states: they [the language designers] felt it was not an important use case scenario to support implicit extension methods (to give the beast a name) from within the type because it would encourage extension methods that really should be instance methods and it was considered plain unnecessary.
Now, it is hard to find out what is happening exactly under the covers but from some playing around we can deduce that base.X() does not help us. I can only assume that base.X performs its virtual call as X() and not this.X() from the context of the baseclass.
What do I do when I want to call the extension method of a baseclass from a subclass?
Frankly, I haven't found any truly elegant solution. Consider this scenario:
public class Base
{
protected void BaseMethod()
{
this.ExtensionMethod();
}
}
public class Sub : Base
{
public void SubMethod()
{
// What comes here?
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base)
{
Console.WriteLine ("base");
}
public static void ExtensionMethod(this Sub sub)
{
Console.WriteLine ("sub");
}
}
There are 3 ways (leaving aside reflection) to call the ExtensionMethod(Base) overload:
Calling BaseMethod() which forms a proxy between the subclass and the extensionmethod.
You can use BaseMethod(), base.BaseMethod() and this.BaseMethod() for this since now you're just dealing with a normal instance method which in its turn will invoke the extension method. This is a fairly okay solution since you're not polluting the public API but you also have to provide a separate method to do something that should have been accessible in the context in the first place.
Using the extension method as a static method
You can also use the primitive way of writing an extension method by skipping the syntactic sugar and going straight to what it will be compiled as. Now you can pass in a parameter so the compiler doesn't get all confused. Obviously we'll pass a casted version of the current instance so we're targetting the correct overload:
Extensions.ExtensionMethod((Base) this);
Use the - what should be identical translation - of base.ExtensionMethod()
This is inspired by #Mike z's remark about the language spec which says the following:
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
The spec literally says that base.I will be invoked as ((B) this).I. However in our situation, base.ExtensionMethod(); will throw a compilation error while ((Base) this).ExtensionMethod(); will work perfectly.
It looks like something is wrong either in the documentation or in the compiler but that conclusion should be drawn by someone with deeper knowledge in the matter (paging Dr. Lippert).
Isn't this confusing?
Yes, I would say it is. It kind of feels like a black hole within the C# spec: practically everything works flawlessly but then suddenly you have to jump through some hoops because the compiler doesn't know to inject the current instance in the method call in this scenario.
In fact, intellisense is confused about this situation as well:
We have already determined that that call can never work, yet intellisense believes it might. Also notice how it adds "using PortableClassLibrary" behind the name, indicating that a using directive will be added. This is impossible because the current namespace is in fact PortableClassLibrary. But of course when you actually add that method call:
and everything doesn't work as expected.
Perhaps a conclusion?
The main conclusion is simple: it would have been nice if this niche usage of extension methods would be supported. The main argument for not implementing it was because it would encourage people to write extension methods instead of instance methods.
The obvious problem here is of course that you might not always have access to the base class which makes extension methods a must but by the current implementation it is not possible.
Or, as we've seen, not possibly with the cute syntax.
Try to cast the instance to its base class:
((BaseClass)this).ExtensionMethod()
Applied to your code:
public class Base
{
public void BaseMethod()
{
}
}
public static class BaseExtensions
{
public static void ExtensionMethod(this Base baseObj) { }
}
public class Sub : Base
{
public void SubMethod()
{
( (Base) this).ExtensionMethod();
}
}

Why can't a static and non-static method share the same signature?

C# provides following signature characteristics to be used while function overloading.
We know that for overloading takes into consideration only arguments; their number and types, but the objective of polymorphism is to provide same name but different usage depending upon calling strategy.
If I have a class containing two methods with the same name and signature, while one is static and another is not, C# compiler throws an error; "Class already defines a member called 'foo' with the same parameter types".​The call to both the methods are going to be different; one with the object name and the static one with a class name. Hence there is no ambiguity with calling strategy. Then why does it throw an error?
class Example {
public void foo() { }
public static void foo() { }
}
class Program
{
static void Main(string[] args)
{
Example e = new Example();
e.foo();
}
}
Reason why it is throwing an error is that static methods can be called from non-static methods without specifying type name. In this case, compiler won't be able to determine, which method is being called.
public class Foo()
{
public static void MyMethod() {};
public void MyMethod() {}
public void SomeOtherMethod()
{
MyMethod(); // which method we're calling static or non-static ?
}
}
EDIT
Just found this SO post regarding your case. You might want to check it also.
This error occurs because this is how the behavior is defined in the C# Language Specification. Any "ambiguous" usage (or ways to disambiguate such) is irrelevant, although such reasoning and edge-cases may have led the designers to not explicitly allow such a differentiation .. or it might simply be a C# codification of an underlying .NET CLI/CLR restriction1.
From "3.6 Signatures and overloading" in the C# specification (and in agreement with the linked documentation), formatted as bullets:
The signature of a method consists of
the name of the method,
the number of type parameters, and
the type and kind (value, reference, or output) of each of its formal parameters ..
Method modifiers, including static, are not considered as part of the method signature here.
And, from "1.6.6 Methods" we have the restriction and an agreeing summary:
The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and {the number, modifiers, and types of} its parameters..
This restriction applies before (and independently of) the method being considered for polymorphism.
Also, as a closing note: instance methods must be virtual or accessed through an interface to be run-time polymorphic in C#. (Both method hiding and method overloading are arguably a form of compile-time polymorphism, but that's another topic..)
1There is support for this simply being the result of a restriction of the .NET CLI/CLR itself that is not worth bypassing (ie. for interoperability reasons). From "I.8.6.1.5 Method signatures" in ECMA-335:
A method signature is composed of
a calling convention [CLS Rule 15: "the only calling convention
supported by the CLS is the standard managed calling convention"],
the number of generic parameters, if the method is generic,
[omitted rule]
a list of zero or more parameter signatures—one for each parameter of the method—
and,
a type signature for the result value, if one is produced.
Method signatures are declared by method definitions. Only one constraint can be added to a
method signature in addition to those of parameter signatures [CLS Rule 15: "The vararg constraint is not part of the CLS"]:
The vararg constraint can be included to indicate that all arguments past this point are
optional. When it appears, the calling convention shall be one that supports variable
argument lists.
The intersection between the C#/CLS and ECMA signature components is thus the method name, "the number of generic parameters", and "a list of zero or more parameter signatures".
I feel your question is "why did the standard choose to forbid declaring two methods that differ only by the static keyword?", and therefore the answer "because the standard says so" does not look appropriate to me.
Now, the problem is, there could be any reason. The standard is the Law, and it can be arbitrary. Without the help of somebody who participated to the language's design, all we can do is speculate about the reasons, trying to uncover the spirit of the Laws.
Here is my guess. I see three main reasons for this choice:
Because other languages say so.
C++ and Java are inspirational languages for C#, and it makes sense to observe the same overloading rules as those languages. As to why it is this way in these languages, I don't know. I found a similar question on SO about C++, although no answer is given as to why it is this way (outside of "the standard says so").
Because it creates ambiguity that need to be resolved.
As others and OP noted, allowing the same signatures excepted for the static keyword forces the user to call the methods in an unambiguous way (by prefixing the class name or the instance name). This adds a level of complexity to the code. Of course this can already be done with fields and parameters. However some don't agree with this usage and prefer to choose different names (prefixing the fields with _ or m_) for the fields.
Because it does not make a lot of sense in OOP.
This is really my understanding here, so I could be completely wrong (at least #user2864740 thinks that the argument is dubious -- see comments), but I feel like static members are a way to introduce "functional programming" in OOP. They are not bound to a specific instance, so they don't modify the internal state of an object (if they modify the state of another object, then they should be a non-static method of this other object), in a way they are "pure".
Therefore I don't understand how a "pure function" could be semantically close enough of a regular object method so that they would share the same name.
The same question was asked to Eric Gunnerson, who worked on the C# language design team, and his answer was:
It is true that there would be no ambiguity between the two functions as far as a compiler is concerned. There would, however, be a considerable potential for confusion on the part of the user. It would be tough to find the right method in documentation, and once you did, hard to be sure that you are calling the right version (ie you could accidentally call the static version when you wanted the instance version).
Therefore, the reason it is not allowed is by design.
i) Problem hypothesis - obtain the following behavior :
Be able to call a static method off of a class: e.g. MyClass.MySpecialMethod()
Also be able to call a non-static method with the same return type, name and arguments off of an instance of the same class: e.g. instanceOfMyClass.MySpecialMethod()
ii) Context :
Reproduce the behavior inside an application that uses Dependency Injection.
Most of today's programming uses DI - it is almost an anti-pattern to call a non-static method off of a direct instance of a dependency (without that dependency having been previously injected with DI).
iii) Solution :
class Program
{
static void Main(string[] args)
{
// instead of class initialization we would have these registrations, e.g.:
// diContainer.Resolve<IMyApplication>().With<MyDIApplication>();
// diContainer.Resolve<ITerminator>().With<Terminator>();
IMyApplication app = new MyDIApplication(new Terminator());
app.Run();
}
public interface IMyApplication { void Run(); }
public class MyDIApplication : IMyApplication
{
private readonly ITerminator terminator;
public MyDIApplication(ITerminator terminatorDependency)
{
this.terminator = terminatorDependency;
}
public void Run()
{
terminator.Terminate(); // instance method call
Terminator.Terminate(); // static method call
}
}
public interface ITerminator { void Terminate(); }
public class Terminator : ITerminator
{
public static void Terminate() => Console.WriteLine("Static method call.");
void ITerminator.Terminate() => Console.WriteLine("Non-static method call.");
}
}
Conclusion:
Yes, the signatures of the two Terminate methods are not identical, because the non-static method is an explicit implementation of the interface which does not conflict with the static method,
But in truth, when using this solution in the context of dependency injection, what we really care about is the outcome, not the plumbing - which is that we managed to call a static method off a class, with practically the same return, name and args as a non-static method off an instance of that class injected with DI.
Check out this simple pseudo-code:
class A
{
public void B(){...}
public static void B(){...}
}
...
A A = new A();
A.B(); // <== which one is going to be called?

Why to use call backs when same thing can be done just by calling the method

I understand that callbacks are methods it self , and are passed as an argument to another method.
But why do we need to pass method as an argument while we can directly do that just by calling the method.
For Example:
private static void TakeAction(Action<String> action)
{
}
TakeAction((s) => { Console.WriteLine(s); });
The same can be done just by doing:
private static void TakeAction()
{
Fo1();
}
private static void Fo1(string s)
{
Console.WriteLine(s);
}
So why Callback? What specific problem does it address?
You have a compile time reference to Fo1 method, so you just call it. What if you don't know the method in compile time? How'll you call it? That's why Delegates are useful.
Can you imagine "Linq" without Delegates(or callback as you said). Without delegates linq is nothing. How .Net framework can call your method(defined in your own assembly).?
Well, there is a way. we can use interfaces, but that's no different from java way of doing it. This is c# way of doing it.
with delegates
By defining a delegate, you are saying to the user of your class
"Please feel free to put any method that match this signature here and
it will be called each time my delegate is called"
I think thats enough to let u know Why to use call backs when same thing can be done just by calling the method
Delegates (you call them callbacks) are types, which describes what kind of a method they can store in a variable. That gives you an option to choose dynamically which method program uses without a need to use whole Command Pattern (where you have to define a class which implements an interface with a method of your choice).

Extension method vs static method precedence

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?
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.
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.
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.

object - How top most base class got Method. [Extension Method]

Yesterday i gone through some article about EventAggregator, there some shot of code written like this,
(Message.Text as object).PublishEvent(PublishEventNames.MessageTextChanged);
public static class ExtensionServices
{
//Supplying event broking mechanizm to each object in the application.
public static void PublishEvent<TEventsubject>(this TEventsubject eventArgs, string eventTopic)
{
ServicesFactory.EventService.GetEvent<GenericEvent<TEventsubject>>()
.Publish(new EventParameters<TEventsubject> { Topic = eventTopic, Value = eventArgs });
}
}
My question is, how the object got the method "PublishEvent". Is my OOP understanding is wrong?
It was implemented as an Extension Method on the object class.
For example, this extension method (from the linked article):
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
Is defined on the String class (by using the this String syntax and a static method on a static class) .
In the project that this is defined in String now has a WordCount method (so long as it is also in the correct namespace).
Extension methods are not actually part of the object that you appear to call the method on. Extension methods are in an additional lookup scope that the compiler looks in after looking for the method in the scope of the object itself.
So, for a method call like obj.MyExtension(), the compiler will look for "MyExtension" in the members of the type of the obj variable. It won't find any matches, because "MyExtension" isn't defined in the object's type. The compiler then looks for extension methods named "MyExtension" that are available in the current scope (because of using clauses) that have a this parameter whose type matches the type of the obj instance variable. If a match is found, then the compiler generates code to make a static method call that other method, passing obj in the this parameter.
I believe the extension methods scope is a "last chance" lookup - if the compiler can't find "MyExtension" in the available extensions, the next step is to fail with a compile error.
The tricky thing with extension methods is they're only accessible when you have added the appropriate using clause to the current source file and added a reference to the appropriate assembly that implements the extensions to bring them into scope.
Intellisense doesn't help you resolve these names by adding the appropriate using clause for you. As a user, you get used to calling a particular method on a particular type of object, and you mentally associate that method as being part of that type. When you're fleshing out a new source file it's very common to write calls to that method as you normally would and get "not found" compiler errors because you forgot to reference the namespace / assembly containing the extension method definition(s) to your source file.
The this part of this TEventsubject eventArgs determines that this is an Extension method.
It is only syntactic sugar to be able to write
TEventsubject eventArgs;
eventArgs.PublishEvent("topic");
Instead of
TEventsubject eventArgs;
ExtensionServices.PublishEvent(eventArgs, "topic");
PublishEvent is an extension method.
You can tell by the definition of the method, which includes the this keyword in the arguments list.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Extension methods are very useful syntactically; but they should be used judiciously:
1) They can clutter Intellisense if too many extensions are added for non-specific types (such as an object).
2) They should be used to augment class/interface inheritance, not replace it. IMO, If a method is shared across completely unrelated types, then it is a good candidate for an extension method. But if it is shared across related types, then it is a better candidate for a method in a base class.

Categories

Resources