Thursday 15 February 2007

C# 3.0 Extension Methods

Mono compiler gets the full support of extension methods, the first C# 3.0 feature. A patch which adds extension methods support to gmcs just landed on SVN. Let’s look at some interesting details.

Extension methods are static methods that can be invoked using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods. -- C# 3.0 Specification

Sounds good, so how can I make my method extension method?

A method became the extension method when the first method parameter contains `this’ modifier. Extension methods can be declared in non-generic top-level static classes which mean that extension methods can be declared as static only. There are further limitations but they only covering corner cases. For those interested, I recommend browsing Mono compiler test suite to get some ideas.
static class MyExtension
{
public static string Prefix (this string s, string prefix)
{
return prefix + s;
}
}

class M
{
public static void Main ()
{
string s = "abc".Prefix ("1");
}
}

Note: If you want to use extension methods you need to pass `langversion:linq’ option to compiler to unlock C# 3.0 specific features; although extension methods are included in gmcs compiler.

When you try to compile the sample, it will compile successfully and an instance method call will be converted to a static method call by compiler. How is it possible? The method `Prefix’ is the extension method of `string’ class and no other method with same parameters exists and therefore the method is selected as the best overload candidate.

Wishing to use extension methods in more advanced scenario, things become little bit more complicated and you have to use `using ’ to import your extension methods from different namespace or an assembly.

Confusing, isn’t it? Well, not that much. Extension methods are included in method resolving process if standard (non-extension) process failed to find a match. The compiler will look for extension methods in the current namespace context and if no suitable method was found, the process will continue inspecting all referenced namespaces in the current namespace. In the case of method was not found, the compiler continues in parent namespace until either method is found or parent namespace does not exist.

My overall feeling about the feature is mixed as extension methods clearly reduce code readability. Fortunately, I was pleased to read the recommendation "to use extension methods sparingly and only if it is not possible to use instance methods" directly inside C# Standard.

4 comments:

asbjornu said...

I find extension methods extremely useful as a way to add methods to existing classes (perhaps sealed ones) without having to inherit the class. Very handy if you think the string class needs a bit more sugar. Creating your own string class is too much work and creating a MyStringManipulation library is awkward and non-intuitive in use.

Anonymous said...

“Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.”

Just a reminder. ;-)

Anonymous said...

Well put Jakub, I fear feature bloat.

Anonymous said...

Thanks for the nice post!