Search Eridotnet

 

Thursday, January 24, 2008

Quick thoughts on .NET 1.x, 2.0, 3.0 and 3.5 (part five: extension methods)

Ahh... I enjoy the comments on my other previous post, part three of my quick thoughts. I hope it really open the minds of Indonesian software developers about .NET progress and its current/latest features.

Now, I'm going to talk about extension methods. According to Visual C# 2008 (C# 3.0) documentation, extension methods are:

"Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type."

Yes, you can add methods to existing types. But this addition has its own requirements, not just simple "add".

Take look at this sample code in C# (from MSDN):

    /// <summary>
/// Extension methods must be inside of a public static class
/// </summary>
public static class StringExtension1
{
// This is the extension method.
// The first parameter takes the "this" modifier
// and specifies the type for which the method is defined.
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
    class Program
{
static void Main(string[] args)
{
string s = "The quick brown fox jumped over the lazy dog.";
// Call the method as if it were an
// instance method on the type. Note that the first
// parameter is not specified by the calling code.
int i = s.WordCount();
Console.WriteLine("Word count of s is {0}", i);
Console.ReadLine();
}
}

As you can see, String has additional method, WordCount(). It returns number of words in a hard coded sentence as a value of String s. There's no magic here, only the compiler can decide at runtime where to look for this method, after searching through static classes. The static classes doesn't have to be in the same namespace as your code. After it find the method, it translates into an execution of the static method of StringExtension1 class at runtime.


Still, the conclusion is, this is a proof that there's no change in CLR since CLR in .NET 2.0. A language features? No. It's more correct if you simply say it as a compiler feature. Why? Since it's more emphasized in compilation time.


The requirement of extension methods are (also as step by step guide, taken from MSDN):



  1. Define a static class to contain the extension method.
  2. The class must be visible to client code. For more information about accessibility rules, see Access Modifiers (C# Programming Guide).
  3. Implement the extension method as a static method with at least the same visibility as the containing class.
  4. The first parameter of the method specifies the type that the method operates on; it must be preceded with the this modifier.
  5. In the calling code, add a using directive to specify the namespace that contains the extension method class.
  6. Call the methods as if they were instance methods on the type.
  7. Note that the first parameter is not specified by calling code because it represents the type on which the operator is being applied, and the compiler already knows the type of your object. You only have to provide arguments for parameters 2 through n.

The sample above is an extension method that has no parameter. What if I want parameters?


This is the sample:

    public static class StringExtensionParams
{
public static String Greetings(this String s, String name, string salutation)
{
StringBuilder sb = new StringBuilder();
sb.Append("Hello ");
sb.Append(salutation);
sb.Append(" ");
sb.Append(name);
sb.Append("! ");
sb.Append(s);
return sb.ToString();
}
}

This is the code that use Greetings:

    class Program
{
static void Main(string[] args)
{
string s = "The quick brown fox jumped over the lazy dog.";
// Call the method as if it were an
// instance method on the type. Note that the first
// parameter is not specified by the calling code.
int i = s.WordCount();
Console.WriteLine("Word count of s is {0}", i);
String str1 = DateTime.Now.ToLongDateString();
String str2 = str1.Greetings("Eriawan", "Mister");
Console.WriteLine(str2);
Console.ReadLine();
}
}

Pretty cool, isn't it? But one thing is, be careful with the name of the extension method. You can get errors if you extend some type that already has some extension methods with the same name somewhere else in your project.


 

Happy coding! Next blog stop: LINQ and Extension methods usage!



kick it on DotNetKicks.com

2 comments:

Yogesh said...

Extension methods are available to .NetFx 2.0 developers too. What all they need to define is:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false)]
public sealed class ExtensionAttribute : Attribute
{
}
}
... and extension methods will work perfect with Fx2.0 also. :)

Eriawan Kusumawardhono said...

Thanks for your comments!

I'm afraid you're wrong about the use of this attribute in .NET 2.0. This attribute is only available in .NET 3.5 only.

On the online MSDN library:

http://msdn2.microsoft.com/en-us/library/system.runtime.compilerservices.extensionattribute.aspx

It clearly defines that this attribute only available in .NET 3.5. Please read carefully on the section "Version Information". It is recommended also to use this attribute for your own compiler services.

VB.NET 9.0 and C# 3.0 already have supports for extension method using this attribute implicitly thru the C# 3.0 and VB.NET 9.0 compilers.