This is an extension method but I am confuse with the difference of the two dot operator.
public static int WordCount(this string str)
{
int count = str.Split(new char[] { ' ', '.', '?', '!' },
StringSplitOptions.RemoveEmptyEntries).Length;
return count;
}
string str = "Hello, How are you?";
Console.WriteLine(str.WordCount());
Console.WriteLine(ExtensionMethods.WordCount(str));
Extension methods is nice feature of C# that were developed to allow to add features to classes you cannot modify or inherit from.
Extension method is a static method. CLR does not create any special IL code for extension method.
As General Guidelines of C# Programming Guide says: (special thanks to Lei Yang)
While it's still considered preferable to add functionality by
modifying an object's code or deriving a new type whenever it's
reasonable and possible to do so, extension methods have become a
crucial option for creating reusable functionality throughout the .NET
ecosystem. For those occasions when the original source isn't under
your control, when a derived object is inappropriate or impossible, or
when the functionality shouldn't be exposed beyond its applicable
scope, Extension methods are an excellent choice.
When using an extension method to extend a type whose source code you aren't in
control of, you run the risk that a change in the implementation of
the type will cause your extension method to break.
If you do implement extension methods for a given type, remember the
following points:
An extension method will never be called if it has the same signature
as a method defined in the type. Extension methods are brought into
scope at the namespace level. For example, if you have multiple static
classes that contain extension methods in a single namespace named
Extensions, they'll all be brought into scope by the using Extensions;
directive.
Related
This question already has answers here:
Why are extension methods only allowed in non-nested, non-generic static class?
(3 answers)
Closed 9 years ago.
I understand that C# extension methods must be static. What I don't understand is why these extensions can't be defined in non static classes or generic ones?
Update: I am interested in the reason behind this design decision.
This is more of an observation than an answer, but...
When you call an instance method, a reference to the object you are calling is pushed onto the stack as the first argument in your method call. That first argument is "this" and is done implicitly.
When you define an extension method, you explicitly define a "this" as the first argument.
Is it possible that method resolution would be confusing if you could define extension methods and instance methods in the same class i.e. defining methods with the same name and, in effect, the same parameters when the "this" parameter is included.
Take a look to this piece of the .NET C# specification:
When the first parameter of a method includes the this modifier, that
method is said to be an extension method. Extension methods can only
be declared in non-generic, non-nested static classes. The first
parameter of an extension method can have no modifiers other than
this, and the parameter type cannot be a pointer type.
And this fragment from Jon Skeet's answer:
It's not clear to me why all of these restrictions are necessary -
other than potentially for compiler (and language spec) simplicity. I
can see why it makes sense to restrict it to non-generic types, but I
can't immediately see why they have to be non-nested and static. I
suspect it makes the lookup rules considerably simpler if you don't
have to worry about types contained within the current type etc, but I
dare say it would be possible.
Because the spec says so... Now there are probably good reasons why they wrote the spec this way.
The reason why they can't be declared in generic classes is quite obvious: given the way extension methods are called, where would you specify the type argument for the class?
The reason why it must be a static class is less obvious, but I think it makes sense. The main use case for static classes is to group helper methods together (e.g. Path, Directory, ProtectedData...), and extension methods are basically helper methods. It wouldn't make sense to be able to create an instance of Enumerable or Queryable, for example.
I was just curious to know how Extension methods are hooked up to the Original class. I know in IL code it gives a call to Static Method, but how it does that and why dosen't it break encapsulation.
They don't "hook up".
The Visaul Studio IDE just makes it look like it does by showing them in the intellisense lists.
The compiler "knows" how to deal with the references in order to make the right method calls with the correct parameters.
This is simply syntactic sugar - the methods are simply static methods on a separate static class. Using the this modifier lets the compiler "know" to add the ExtensionAttribute to the class to mark it as an extension method.
Since extension methods do not in fact change the class and can only access public members on it, encapsulation is retained.
From MSDN:
Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.
(emphasis mine)
Extension methods are specified by putting the this keyword in front of the first parameter of a static method:
public static void SomeExtension(this string s)
{
...
}
That is just syntactic sugar for decorating the method with System.Runtime.CompilerServices.ExtensionAttribute:
[Extension]
public static void SomeExtension(string s)
{
...
}
When the compiler sees that attribute, it knows to translate the extension method call to the appropriate static method call, passing the instance as the first parameter.
Since the calls are just normal static method calls, there is no chance to break encapsulation; the methods, like all static methods, only have access to the public interfaces of the extended types.
Extension methods are just syntactic sugar, they are just static methods. You are only able to access public fields or properties in them, just like normal static methods.
The key ingredient is that an instance method of a class isn't fundamentally different from a static method. With one small detail, they have a hidden argument. For example, the String.IndexOf(char) method actually looks like this to the CLR:
public static int IndexOf(string thisRef, char value) {
// etc...
}
The thisRef argument is what supplies the string reference whenever you use this in your code or access a member of the class. As you can see, it is a very small step from an extension method to an instance method. No changes were necessary in the CLR to support the feature.
One other minor difference is that the compiler emits code that checks if this is null for an instance method but does not do so for an extension method. You can call an extension method on a null object. While that might look like a feature, it is actually a restriction induced by the extension method not actually being a member of the class.
Internally, the CLR keeps a list of methods for the class, the MethodTable. Extension methods are not in them, preventing the compiler from emitting the callvirt IL instruction, the 'trick' that it uses to get the cheap null check. Explicitly emitting code to make the null check would have been possible but they elected not to do so. Not quite sure why.
Another automatic consequence of this is that an extension method cannot be virtual.
I think you should have a look at http://go.microsoft.com/fwlink/?LinkId=112388
I just looked at this posting: What is the best or most interesting use of Extension Methods you’ve seen?
I've never heard of extension methods. Do they apply to every language?
What is the point of them? In that particular posting I did not understand the example.
No, they do not apply to every language. They are a language-specific feature, offered by C# and Visual Basic (other languages may have adopted them since, I don't know).
The point of them is to provide a convenient syntax for calling utility methods on a class or interface. In C# 2, a utility method would be called through a static class, passing the argument in the normal way:
IEnumerable<string> someStrings;
int count = EnumerableHelpers.Count(someStrings);
With extension methods, this can be written more conveniently using something that looks like normal member method syntax:
int count = someStrings.Count();
even though Count() is not a member of the IEnumerable<string> interface. So extension methods let you appear to add members to classes or interfaces that you don't control.
They are available to C# and VB. They allow you to simulate the addition of methods to classes that are not under your control.
You could, for instance, you could add a WordCount method to string.
So instead of
MyStringUtils.WordCount( "some string" )
You could just write "some string".WordCount().
public static class MyExtensions
{
public static int WordCount(this String str)
{
return MyStringUtils.WordCount( str );
}
}
This is strictly "syntactic sugar" and aids in readability. You're essentially creating a static method that will be shown in the IntelliSense for the target type.
do they apply to every language?
No, but some languages have the same feature, though not necessarily under the same name. Those I know about are Objective-C and Groovy, where the feature is called "Categories".
What is the general thinking on the use of extension methods that serve no purpose other than enhancing readability?
Without using extension methods we might have the method
IEnumerable<DependencyObject> GetDescendents(DependencyObject root) {}
that could be called with
var descendents = GetDescendents(someControl);
or
foreach (var descendent in GetDescendents(someControl)) {}
Although there's nothing wrong with this I find the instance.method() notation to be more readable so I might consider making this an extension method with this signature
public IEnumerable<DependencyObject> GetDescendents(this DependencyObject root) {}
allowing it to be called with
var descendents = someControl.GetDescendents();
or
foreach (var descendent in someControl.GetDescendents()) {}
So my question is whether you think this is reasonable or an abuse of extension methods. If it was simply a matter of declaring the function differently I wouldn't hesitate; but the fact that using an extension method requires it be coded in a different, static class makes me wonder if it's worth the effort or not. The example I'm using above is a fairly generic one and might have merit as an extension method that will be used in several places but often this is not the case and I would be coding the static class containing the extension in the same file as the single class that uses it.
I think the big advantage of extension methods is discoverability. If someone is unaware that one of their team members created a GetDescendents method in a utility class somewhere, they'll never use it. However, if that method starts to show up in Intellisense or in the Object Browser, there's a decent chance they will stumble across it. If you start to make more extensive use of extension methods, people will start to use the tools I mentioned to look for extensions that add value.
Most if not all extension methods fall into this category to some degree, since they can't operate on the internals of a class anymore than your static function. At any rate, any extension method can be rewritten in a static class with an extra parameter representing the object (arguably, that's exactly what an extension method is anyway).
To me, it's entirely a question of style: in the example you provided, I'd probably jump for the extension method. I think the important question here is, Is this function something I'd write as part of the class if I were to reimplement the class, and does it make sense as such? If yes, then go for it, if no, then consider a different solution.
An extension method only exists to improve readability - it is merely a syntax shortcut that allows you, by specifying the this keyword on the first argument, allows you to call the method on the object instance in question. So I think it is entirely reasonable.
Recently I asked a question about how to clean up what I considered ugly code. One recommendation was to create an Extension Method that would perform the desired function and return back what I wanted. My first thought was 'Great! How cool are Extensions...' but after a little more thinking I am starting to have second thoughts about using Extensions...
My main concern is that it seems like Extensions are a custom 'shortcut' that can make it hard for other developers to follow. I understand using an Extension can help make the code syntax easier to read, but what about following the voice behind the curtain?
Take for example my previous questions code snippet:
if (entry.Properties["something"].Value != null)
attribs.something = entry.Properties["something"].Value.ToString();
Now replace it with an Extension:
public static class ObjectExtensions
{
public static string NullSafeToString(this object obj)
{
return obj != null ? obj.ToString() : String.Empty;
}
}
and call using the syntax:
attribs.something = entry.Properties["something"].Value.NullSafeToString();
Definetely a handy way to go, but is it really worth the overhead of another class object? And what happens if someone wants to reuse my code snippet but doesn't understand Extension? I could have just as easily used the syntax with the same result:
attribs.something = (entry.Properties["something"].Value ?? string.Empty).ToString()
So I did a little digging and found a couple of articles that talked about the pros/cons of using Extensions. For those inclined have a look at the following links:
MSDN: Extension Methods
Extension Methods Best Practice
Extension Methods
I can't really decide which is the better way to go. Custom Extensions that do what I want them to do or more displayed code to accomplish the same task? I would be really interested in learning what 'real' developers think about this topic...
Personally I think the "problems" of extension method readability are vastly overstated. If you concentrate on making your code easy to read in terms of what it's doing, that's more important most of the time than how it's doing it. If the developer wants to trace through and find out what's actually happening behind the scenes, they can always click through to the implementation.
My main problem with extension methods is their discovery method - i.e. via a specified namespace instead of a specified class. That's a different matter though :)
I'm not suggesting that you put in extension methods arbitrarily, but I would seriously consider how often you need to know how every expression in a method works vs skimming through it to see what it does in broader terms.
EDIT: Your use of terminology may be misleading you slightly. There's no such thing as an "extension object" - there are only "extension methods" and they have to exist in static types. So you may need to introduce a new type but you're not creating any more objects.
[OP] Definetely a handy way to go, but is it really worth the overhead of another class object?
No extra class object is created in this scenario. Under the hood, extension methods are called no differently than a static method. There is an extra metadata entry for the extension method container but that is pretty minimal.
[OP] And what happens if someone wants to reuse my code snippet but doesn't understand Extension Objects?
Then it would be a good time to educate them :). Yes, there is the risk that a new developer may not be comfortable with extension methods to start. But this is hardly an isolated feature. It's being used more and more in all of the code samples I'm seeing internally and on the web. It's something that is definitely worth while for a developer to learn. I don't think it fits into the category of "to esoteric to expect people to know"
The only serious weirdness to deal with in Extension methods are:
They do not have to cause a null reference exception if the left hand side (the object on which it appears you are invoking a method) is null.
can sometimes be useful, but is contrary to expectations as such should be used with extreme caution.
They are not accessible through reflection on the classes/interfaces to which they apply.
generally not a problem, but worth keeping in mind.
Name collisions with other extension methods involve a lengthy resolution rule sequence
if you care the sequence is to prefer:
Extension methods defined inside the current module.
Extension methods defined inside data types in the current namespace or any one of its parents, with child namespaces having higher precedence than parent namespaces.
Extension methods defined inside any type imports in the current file.
Extension methods defined inside any namespace imports in the current file.
Extension methods defined inside any project-level type imports.
Extension methods defined inside any project-level namespace imports.
[OP] And what happens if someone wants to reuse my code snippet but doesn't understand Extension Objects?
The extension methods will not show in the intellisense for the object if the assembly that implements them is not references in the project. Your code snippet will also not compile. That could potentially create a bit of a confusion to the other developer.
If the extension method assembly is referenced, it will show in the intellisense, but it will be not mentioned in the documentation for the object. This could potentially cause a bit of confusion as well.
However, as #JaredPar mentioned, the extension methods as a technique are used more and more and I would expect most of the C# programmers to know about them. Thus, I wound't be too worried about any potential confusion.
C# Extensions is an additional "tool" provided by .Net in order to help you write your code a little bit nicer. Another advantage of them is, that they handle null. Although they seem very usable, I try to use them only in certain cases that will really tidy up my code, because they are not standard coding methods and they stand a little bit seperate from other classes as they have to be in static classes and are static themselves.
Let's say their implementation is a little bit untidy, but their use is made tidier.
It is also important to mention that they only exist in C# and VB.Net (Java doesn't have Extensions). Another important fact is that Extensions have no priority over standard methods, meaning that if a method is implemented in a class with the same name as an extension method on the same class, then the first method is the one that will be called and not the extension method.
Below there are three cases where I often use them, why I use them and alternative solutions that would solve the same problem:
1. To implement specific methods for generic classes:
I have a generic type, let's say a collection List<T>. I want to do a method that applies only to a specific kind of list. Let's say a method that creates a union from a list of strings using a seperator
("A", "B", "C", " sep " --> "A sep B sep C"):
public static string union(this List<string> stringList, String seperator)
{
String unionString = "";
foreach (string stringItem in stringList) {
unionString += seperator + stringItem; }
if (unionString != "") {
unionString = unionString.Substring(seperator.Length); }
return unionString;
}
In case I didn't want to use an extension, I would have to create a new class "StringCollection : List<string>" and implement my method there. This is mainly not a problem and it is actually better in most cases, but not in all cases. If for example you are receiving all your data in lists of strings in many cases, you don't have to convert those lists in StringCollections each time you want to use union, but use an extension instead.
2. To implement methods that need to handle null:
I need a method to convert an object to a string without throwing an exception in case the object is null
public static String toStringNullAllowed(this Object inputObject)
{
if (inputObject == null) { return null; }
return inputObject.ToString();
}
In case I didn't want to use an extension, I would have to create a class (probably static), for example StringConverter, which will do the same job, with more words than a simple myObject.toStringNullAllowed();
3. To extend value types or sealed classes:
Value types such as int, float, string, etc as well as sealed classes (classes that cannot be inherited) cannot be extended through inheritance. Below you can see an example of extending integers to be able to be converted to x-digit Strings (for example integer 34, digits 5 --> "00034"):
public static String toXDigit(this int inputInteger, int x)
{
String xDigitNumber = inputInteger.ToString();
while (xDigitNumber.Length < x) { xDigitNumber = "0" + xDigitNumber; }
return xDigitNumber;
}
Again an alternative solution would be a static class (like a toolbox), let's say "Math".
In that case you would write: Math.toXDigit(a, x);
While with the extension method: a.toXDigit(x);
The extension method looks better and is more understandable, like speaking English
To conclude, I guess the disadvantage of extensions is that their implementation is seperated from standard classes and looks a little bit odd or difficult to programmers that are not used to them, while their advantage is that they offer a more understandable, tidier and encapsulated use of the language.