We are currently discussing whether Extension methods in .NET are bad or not. Or under what circumstances Extension methods can introduce hard to find bugs or in any other way behave unexpectedly.
We came up with:
Writing an extension method for types that are not under your control (e.g. extending DirectoryInfo with GetTotalSize(), etc...) is bad, because the owner of the API could introduce a method that hides our extension - and might have different edge cases. For example testing for null in an extension method will automatically translate into a NullReferenceException if the extension method is no longer used due to hiding.
Question:
Are there any other dangerous situations than "hiding" that we are not thinking of?
Edit:
Another very dangerous situation.
Suppose you have an extension method:
namespace Example.ExtensionMethods
{
public static class Extension
{
public static int Conflict(this TestMe obj)
{
return -1;
}
}
}
And use it:
namespace Example.ExtensionMethods.Conflict.Test
{
[TestFixture]
public class ConflictExtensionTest
{
[Test]
public void ConflictTest()
{
TestMe me = new TestMe();
int result = me.Conflict();
Assert.That(result, Is.EqualTo(-1));
}
}
}
Notice that the namespace where you use it is longer.
Now you reference a dll with this:
namespace Example.ExtensionMethods.Conflict
{
public static class ConflictExtension
{
public static int Conflict(this TestMe obj)
{
return 1;
}
}
}
And your Test will fail! It will compile without a compiler error. It will simply fail. Without you even having to specify "using Example.ExtensionMethods.Conflict". The compiler will walk the namespace name and find Example.ExtensionMethods.Conflict.ConflictExtension before Example.ExtensionMethods.Extension and will use that without ever complaining about ambiguous extension methods. Oh the horror!
Some curiosities:
extension methods might be called on null instances; this might be confusing (but sometimes useful)
the "hiding" issue is a biggie if they have different intent
equally, you might get a different extension method with the same name from 2 different namespaces; if you only have one of the two namespaces, this could lead to inconsistent behaviour (depending on which)...
...but if somebody adds a similar (same signature) extension method in a second namespace that your code uses, it will break at compile time (ambiguous)
(edit) And of course, there is the "Nullable<T>/new()" bomb (see here)...
I disagree, the whole point of extension methods is to add your members to black boxed classes. Like everything else there are pitfalls, you must be mindful in naming, implementation and understand the pecking order of the methods.
One breakage we've just found in the MoreLINQ project: if you write a generic extension method, it's impossible to make sure it will work with all types. We've got a method with this signature:
public static IEnumerable<T> Concat<T>(this T head, IEnumerable<T> tail)
You can't use that with:
"foo".Concat(new [] { "tail" });
because of the string.Concat method...
I've used Ruby on Rails for almost as long as I've used C#. Ruby allows you to do something similar to the new extension methods. There are, of course, potential problems if someone named the method the same, but the advantages of being able to add methods to a closed class far outweigh the potential dissadvantage (which would probably be caused by bad design or poor planning).
One thing you can do to make sure extension methods don't conflict with other methods (extension or otherwise) is to use FxCop with rules such as Prevent Duplicate Extension Method Signatures.
First of all I believe your wording is a bit misleading. I take it you're talking about "types" and not "objects".
Secondly, the big advantage of extension methods is that you can add features to type you don't control. If you control the type, why not just modify the type instead of relying on extension methods?
We took the attitude in my team that Extension Methods are so useful that you can't realistically ban them, but so dangerous (principally because of the hiding issue) that you have to be a bit cautious. So we decided that all Extension Method names have to be prefixed with X (so we have a bunch of XInit...() methods to initialise controls in useful ways, for instance). That way a) the likelihood of a naming collision is reduced and b) the programmer knows he is using an Extension Method and not a class method.
What .Net calls extension methods are also a limited form a MonkeyPatching (try to ignore the php rant in there).
That should give you some material for your discussion.
Related
I m a great fan of csharp 4..
i have added too much methods to string object (.net types) as an extension method
consider approximately 200
will that degrads performance?
is it right to add these much methods in .nets library ?
how actually extension methods work internally..?
Well, It is not going to affect runtime performance anyway. Since "Extension Methods" are just compiler trick. Under the hood they are just a static methods in a static class.
public static class MyExt
{
public static void MyExtension(this object obj)
{
//Do something
}
}
public static void Main()
{
object obj = new object();
obj.MyExtension();
//Above line gets compiled into MyExt.MyExtension(obj);
}
As you can see obj.MyExtension(); gets compiled into MyExt.MyExtension(obj); and it is just a method call only. No need of worrying about performance.
If at all you're worried about performance I'd say it won't hurt "runtime performance" though it may or may not hurt compile time performance, Compiler needs to find whether any extension method defined in current namespace as well as imported namespaces.
That is not going to be hard though, since compiler needs to check only static classes. No library is going to have numerous "static classes".
There are no performance penalties for using extension methods, however there is such a thing as bad extension method design. There is a great article about the do's and don'ts of extension methods here: The DOS and DONTS of extension methods.
A contractor where I work is using extension methods to implement CRUD on well-known internal classes that we own. I say it is better to use normal inheritance over extension methods for the following reasons.
Using extension methods obfuscates, hides & confuses the source of the CRUD methods.
I assume extension methods make heavy use of reflection (which is slower).
His logic is, "It's compiled, so it's fast." Maybe I'm wrong...but just because it is compiled doesn't mean it doesn't use reflection, nor does it mean it is faster than normal inheritance.
So my questions are:
How do extension methods work under-the-hood?
Is it better to use inheritance or extension methods on WELL-KNOWN classes that you OWN?
How do extension methods work under-the-hood?
They're just static methods; the compiler rewrites calls like myObject.MyExtensionMethod() to MyExtensionClass.MyExtensionMethod(myObject).
Is it better to use inheretance or extension methods on WELL-KNOWN classes that you OWN?
There's not single answer to this question, it all depends on the context. But usually extension methods are most useful in those cases:
you don't own the code for the extended type
the method targets an interface and will be the same for all implementations of this interface (e.g. IEnumerable<T> and Linq extension methods)
I assume extension methods make heavy use of reflection (which is slower).
No. Extension methods are resolved at compile-time, no reflection required.
That negates your performance concerns.
Is it better to use inheretance or extension methods ?
I would say neither. Use a Repository (DAL). An entity should be persistence-agnostic (so: no inheritance from a base that does CRUD) and not pretend to be involved where it's not (no extensions).
You are right that "Using extension methods obfuscates & confuses the source of the CRUD methods" but inheritance is not the solution.
Description
Extension Methods is a language feature. The compiler makes regular IL (aka MSIL or CIL) code from that. No reflection required.
More Information
MSDN - Extension Methods
Wikipedia - Common Intermediate Language
Your question and the existing answers to it are all missing the bigger picture. New developers joining an on going project should conform to the existing coding styles and standards even if they're not the new persons preferred choices.
If a change in approach represents a major functional improvement as opposed to a primarily esthetic difference it should still be discussed and approved by the entire team first.
Once that's done the change should either be mass implemented and the style guide updated to only contain the new approach, or the old approach should be marked as deprecated and modernized as the code containing it is touched. In the latter case it's best to do commit the cleanup changes separately from the addition/removal/modification of existing functionality so that why the individual modifications in the diff were made is kept clear.
In answer to the first question:
Under the hood, extensions act as Delegates, such that void MyExtension(this object obj) could be rewritten as Action MyDelegate. Where they differ, though, is in syntax when called, as Action must wrap around the object, whereas extensions can be called as if it were a member of the object itself, even though under the hood it is not (nor does it have any direct access to private or protected members of the object, for that matter).
In answer to the second question:
I usually reserve extensions for either classes I do not own or Interfaces.
For example, say you have an interface IAnimal
Public Interface IAnimal
{
void Speak();
void RunToOwnerWhenCalled();
}
And the following classes
public class Mammal
{
public virtual void AnswerWhatAmI()
{
Console.WriteLine("I'm a mammal");
}
}
public class Dog:Mammal, IAnimal
{
public void Speak()
{
Console.WriteLine("arf");
}
public void RunToOwnerWhenCalled()
{
Console.WriteLine("Comming");
}
}
public class Cat:Mammal, IAnimal
{
public void Speak()
{
Console.WriteLine("meow");
}
public void RunToOwnerWhenCalled()
{
Console.WriteLine("I don't know you");
}
}
Then you could have an extension like
Public static void CallAnimal(this IAnimal animal)
{
animal.RunToOwnerWhenCalled();
}
And a method like
Public static void Main
{
Cat cat = new Cat();
cat.CallAnimal();
}
and the result would show the cat's response "I don't know you" in Console.
Consider one more class
Public class Human:Mammal
{
Public Human():base()
{
Console.WriteLine("To be more specific, I am a human.");
}
}
This class wouldn't have the CallAnimal extension, as it does not impliment the IAnimal interface, even though it is a type of Mammal.
Under the hood, an extension method is just like a regular method, and the object it's called on is passed as the first parameter (the this parameter). There's nothing special about an extension method, it's just syntax candy.
It's good practice to avoid extension methods whenever you can. They make the code less readable and less object-oriented.
If it's a class you own, I see no reason to add an extension method to it.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
extension method requires class to be static
In .NET:
Why can't static method in non-static class be an extension method?
Eric Lippert will probably weigh in with a really good answer on this one, but the gist of it will probably be:
We decided it would be easier on both programmers and the compiler if we limit the number of places that you have to look for extension methods.
This policy tends to force users to put all of their extension methods into a few specific classes that are designated for this purpose.
It makes sense that a static class is required to have extension methods. The number one reason is that the static class is stateless ...i.e. you don't have to instance the class. ...but this is just my gut feeling. It wouldn't make sense to me otherwise.
I think, too, that forcing extension methods to reside in public/internal static classes reduces the cost of using them.
Because, well, that's the way it is.
My guess would be that allowing static extension methods would complicate the language (every feature adds complexity of one type or another) while adding almost zero benefit. If you are defining a static method on String for example, what's the benefit in doing so when you can simply define your own class with the same static method?
Instance level extension methods are useful because they work on the current state of a type instance. The static method has no context, so it would not provide any utility over a static method defined elsewhere aside from logical grouping (i.e., defining a String.IsNullOrFullOfSomeChar(char c) would logically make sense to belong to the String class, but aside from that there is no advantage. And yes, that would be a horrible method, just an example).
Extension methods came about as a result of LINQ. They were implemented to get LINQ working the way that the designers wanted. Static extensions were not required and, as such, they were not implemented.
At compile time whenever you use the instance syntax sugar for extension methods, this is converted into a call to the static method (which defines the extension), and passes through your instance.
Apart from the nice syntax it's no different to implementing a static method and passing your instance through as an argument. This is exactly what happens. You can't do this with static classes, as you can't pass a static class as a parameter to a method.
I have a piece of code like the following:
public class ActivityHelper
{
public void SetDate(IList<Activity> anActivityList)
{
foreach(Activity current in anActivityList)
{
current.Date = DateTime.Now;
}
}
//More methods, properties, fields, etc...
}
This could easily be converted to an extension method. For example:
public static void SetDate(this IList<Activity> aList)
{
foreach(Activity current in anActivityList)
{
current.Date = DateTime.Now;
}
}
The original function doesn't use any instance specific data or methods from the ActivityHelper class which makes it seem like it is in the incorrect place. Is this the correct time to write an extension method? What are the correct scenarios in which to create extension methods?
Brad Adams has written about extension method design guidelines:
CONSIDER using extension methods in any of the following scenarios:
To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface. This is because concrete implementations cannot otherwise be assigned to interfaces. For example, the LINQ to Objects operators are implemented as extension methods for all IEnumerable types. Thus, any IEnumerable<> implementation is automatically LINQ-enabled.
When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.
I think Extension methods are only appropriate if there is a compelling reason to make the method an extension method.
If the type is one you do not control, and the method should appear to be integral to the type, or if there is a compelling reason to not put the method directly on the type (such as creating an unwanted dependency) then an extension method could be appropriate.
Personally, if the expectation of the user of your API will already be to use the "ActivityHelper" class when working with collections of Activities, then I would probably not create an extension method for this. A standard, non-extension method will actually be a simpler API, since it's easily understood and discoverable. Extension methods are tricky from a usage standpoint - you're calling a method that "looks like" it exists somewhere other than where it actually exists. While this can simplify syntax, it reduces maintainability and discoverability.
In my experience extension methods work best when they:
Don't have side-effects (most of the extension methods my team wrote that have side-effects, we ended up removing because they caused more problems than they helped)
Offer functionality that applies to every possible instance or value of the type they're extending. (Again citing an example from my team, string.NormalizeUrl() is not appropriate because not all strings are even URLs anyway)
Well i usually create extension methods to help me write codes which have a smooth flow. Its generally depends upon the method you are creating.
If you feel that the method should have already been in framework and is too general then its okay to create an extension method for that.
But you need to first analyze that the class you are extending will always will be in state that your extension method can handle.
For Guidelines here to Brad's Article
http://blogs.msdn.com/b/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx
In essence, Extension Methods provide a more fluent style syntax for Helper methods. This translates into the ability to seemingly add functionality to types or all implementations of interfaces.
However, I generally steer away from declaring Extension Methods with a void returntype, as I feel the usefulness of this fluent style syntax, which allows you to compose statements, is negated when the method in question doesn't return anything.
However, I guess it can be handy to have your methods picked up by IntelliSense... :-)
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?
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.
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();
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.
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.
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.
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.