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.
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.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I often see (in many mocking libraries for example) methods where a generic type argument is used in place of an argument of type System.Type. I am specifically talking about cases where generic type is only being used in typeof(T) operation (i.e. no instance of type T is being used anywhere within the method, and T is not being used for either return type or other arguments).
For example consider following method:
public string GetTypeName(System.Type type) { return type.FullName; }
this method is often accompanied with a generic version:
public string GetTypeName<T>() { return GetTypeName(typeof(T)); }
Questions
is it a bad practice or a good practice?
Is this a syntactic sugar or are there more to it?
I see this as misusing a language feature to abbreviate a call to a method that accepts an argument of type System.Type
Would you consider this a smell? Should this be avoided? or is this actually a good practice (to provide a generic method as a shortcut to avoid typing typeof()).
Here are some practical issues with using this pattern I can think of:
if an argument of non System.Type type is added - method might need to be rewritten (if order of arguments is semantically significant) to non generic version (otherwise some arguments will be generic type arguments, and some will be regular arguments).
it requires two methods (generic and non generic for cases where type is not known at compile time). Consequently adds unit tests which are mostly meaningless.
On the other hand this is a common practice (and majority is always right, right?) but more importantly ReSharper prefers that signature when I do Extract Method refactoring on a code that requires single argument of type System.Type known at compile time (and I learned to take their recommendations though not on faith, but seriously).
I think you need to consider documentation. How obvious is it what the methods do? If you have two methods (one with Type and one with a type argument), users need to look at both and choose. People who aren't looking at your code may not realize that the second one simply calls the first.
Where it definitely makes sense to use both is when the type argument is actually used when it can be and there is some kind of fallback for the Type version. For example:
object GetThingOfType(Type type) { ... }
T GetThingOfType<T>() { return (T)GetThingOfType(typeof(T)); }
Another thing to consider: A type argument must always be written explicitly. If it is likely that there will be more than one operation to perform with the same type object, it's not helpful to use type arguments. Consider something like this:
var t = typeof(string);
var name = GetTypeName(t);
var assemblyName = t.Assembly.FullName;
Even though I know the type is string, I should not write GetTypeName<string> here because I would be repeating myself. By giving me an option that I would most often be better off not choosing, you're adding a bit of unnecessary complexity.
A more obscure point is IDE support of XML documentation. You document the type argument like this:
<typeparam name="T">important information</typeparam>
Then if you type GetTypeName< in C#, Visual Studio will show "T: important information". But, for some reason, when you type GetTypeName(Of in Visual Basic, it will not (as of 2012).
You are right: consider the semantics of the method. Is it operating on instances of the type, or on the type itself?
If it is operating on instances, then it should be a generic method. If it is on the type, then make it an argument of type Type.
So in your example I would say
public string GetTypeName(System.Type type) { return type.FullName; }
Whereas
public static int Count<TSource>(this IEnumerable<TSource> source)
Is operating on the instance source of type IEnumerable<TSource>.
In general, I have seen generics abused more than well-used. Any generic method implementation that does a typeof(T) or worse still, uses any kind of reflection is not really generic in my opinion and is an abuse. After all, generic means it works the same regardless of the type argument, doesn't it?
So, in summary, I agree with you - it smells.
I don't use the string GetName<T>() { return typeof(T).Name; } pattern as it is a misuse (misuse is probably strong but I can't think of the right word) of the design pattern that is the reason for generics, namely: generic type parameters are there for the compiler and the JITter (see the answer to this question) so that they can generate the type specific storage, parameters, stack variables, etc etc.
Using it as a convenient method for passing a type argument at runtime to me smells. There are times when typeof(T) is necessary, but I've found them to be rare and usually needed only when doing complex things with generics, as opposed to simple type safety sorts of things. If I see it, I definately pause and ask myself why it's there.
As it was already said, it looks to me like a matter of personal preferences. From my experience, most of the methods accepting an argument of type Type can be syntactically "sweetened" using an accompanying extension method.
So, in case of your example, I would make the second method an extension. Using this approach, you get a solution for your second concern - no unnecessary unit tests are required. The first one, however, remains; but then, addition of arguments will require refactoring anyway, so it will provide an opportunity to change the consumers of the extension method so they use the modified version of the original one.
Of course, it's just a personal opinion.
A generic method has an advantage over a method with a parameter of type Type, because it can reffer to other generic things using the provided type. This is particularly useful in the following scenario:
public string GetTypeName<T>()
{
return Cache<T>.TypeName;
}
private static class Cache<T>
{
public static readonly TypeName = GetTypeName(typeof(T));
}
This cache is easy, there is no need to mess around with dictionaries and it is automatically thread-safe.
This being said, if the implementation is not using this possibility, than the difference between the two is just cosmetic.
Methods that deal with types usually do just that: Dealing with types.
IMO, Class.Method<SomeType>(); is much better than Class.Method(typeof(SomeType));
But that is a matter of opinion I guess.
Consider LINQ's .OfType<T>(), for example:
personlist.OfType<Employee>().Where(x => x.EmployeeStatus == "Active");
versus:
personlist.OfType(typeof(Employee)).Where(x => ((Employee)x).EmployeeStatus == "Active");
which one would you prefer?
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 wrote an extension method for String to get a char argument, string.Remove(char). But when I used this, it instead called the default string.Remove(int) method.
Shouldn't the presence of an actual method have higher priority than an implicit conversion?
Instance methods have priority over extension methods. Your observation is proof of the same.
When resolving which method to call, it will always pick a matching instance method over an extension method... which is intuitive in a way.
Paraphrased from C# in depth,
When the compiler sees that you're
trying to call a method which looks
like an instance method but is unable
to find one, it then looks for
extension methods (that are visible
based on your using directives). In
case of multiple candidates as the
target extension method, the one with
"better conversion" similar to
overloading (e.g. if IChild and IBase
both have a similar extension method
defined.. IChild.ExtensionMethod is
chosen)
Also a hidden code-breaker could be lets say TypeA didn't have SecretMethod as an instance method in Libv1.0. So you write an extension method SecretMethod. If the author introduces an instance method of the same name and signature in v2.0 (sans the this param), and you recompile your source with the latest-n-greatest Libv2.0, all existing calls to the extension method would silently now be routed to the new instance method.
This behavior is correct. The reason is that introducing an extension method should not change the way existing code executes. Code should behave exactly the same with or without this "superfluous" extension method. It may seem counter-intuitive in certain cases (like yours), but happens for a reason.
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.