C# 3.0: I like Extension Methods
After the declaration of C# 3.0 I went ahead and installed the PDC bits. After reading through the language spec. I was very very very unhappy. I mean we were just getting excited over C#2.0 supporting generics, anonymous mehtods, Nullable types and then suddenly someone ruins all the fun by showing us C#3.0. C#2.0 already appears stale. Some great blogs on this are from Cyrus and Matt Warren
The good part is that since I work in Microsoft, soon (after VS 2005 release I guess) we'd move to C#3.0 to dogfood it. So that means I'll not be required to wait for the super enhancements in C# for long!!!!
I thought I'd try out the features of C#3.0 and write some stuff on it. Here goes the second one (the first is already there)
Extension Methods
With extension methods you can attach additional functionalities to an existing type even if you do not have access to it. For example I can write an extension method Print() which prints each element of any collection on a different line and then invoke it on any collection such as
List<string> first = new List<string>();first.AddRange (new string[] {"Hello", "how"});first.Print();
Importantly note is that even though Print() is not a member of List<> but is still called as if its a method. There are a couple of restrictions in defining the extension method Print. All of which are marked in bold in the example below
public static class Extensions{ public static void Print<T>(this ICollection<T> col) { foreach(T t in col) Console.WriteLine(t); }}static void Main(string[] args){ List<string> first = new List<string>(); first.AddRange (new string[] {"Hello", "how"}); first.Print(); }
The method has to be a static method in a static class. The first parameter to the method has to be qualified using this and this first parameter indicates the types on which this extension method can be applied. Its important to note that this is just syntactic sugar and both the following calls are equivalent and legal.
first.Print();Extensions.Print(first);
So whats the benefit? I think this makes code more elegant and this can be used very much like C++ STL algorithms. Lets say I write a merge algorithm that merges two collections and then I'd be able to call this merge algorithm on any collection in a very elegant way. Following is the implementation of a merge algorithm
using
System;
using System.Collections.Generic;
// Will compile only with C#3.0 complilers
namespace ExtensionMethodDemo
{
public static class Extensions
{
public static void Merge<T>(this ICollection<T> first, ICollection<T> second)
{
foreach(T t in second)
first.Add(t);
}
}
class Program
{
static void Main(string[] args)
{
List<string> first = new List<string>();
first.AddRange (new string[] {"Hello", "how"});
List<string> second = new List<string> ();
second.AddRange (new string[] {"are", "you", "doing"});
first.Merge(second);
}
}
}
Moreover the class libarary already ships with some standard extension methods (like standard algorithms of STL) and you can directly use them. Consider the following
int[] a = new int[] {1, 2, 2, 4, 3};Console.WriteLine(a.Distinct().Count());
Here two of the methods Distinct and Count are used and the combined result is that we get the number of distinct elements in the array and that is 4. This is really really cool.
As a real life sample I wrote a pretty print extension method that prints the directory listing is a pretty fashion.
using
System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.IO;
namespace ExtDemo
{
public static class Extensions
{
public static void PrettyPrint(this IEnumerable<FileInfo> fInfo)
{
ConsoleColor defColor = Console.ForegroundColor;
string format = "{0, -17} {1,10} {2}";
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(format, "Date", "Size (kb)", "File name");
Console.ForegroundColor = defColor;
foreach(FileInfo file in fInfo)
Console.WriteLine(format, file.CreationTime.ToString("dd/MM/yyyy hh:mm"), (float)file.Length / 1024, file.Name);
}
}
class Program
{
static void Main(string[] args)
{
DirectoryInfo dirInfo = new DirectoryInfo(@"c:\");
dirInfo.GetFiles().PrettyPrint();
}
}
}
The C# 3.0 spec clearly calls out that since this is not a very discoverable feature and is somewhat misleading (very much like operator overloading) and so should be used sparingly. I think that this'll be more and more used by class libraries to implement STL like algorithms that can be run on containers.
Comments
Anonymous
September 16, 2005
This is the my third post on the series of post I am making on C#3.0 after it got declared on PDC. See...Anonymous
September 16, 2005
This is the my third post on the series of post I am making on C#3.0 after it got declared on PDC. See...Anonymous
September 17, 2005
This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here,...Anonymous
September 18, 2005
This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous...Anonymous
September 18, 2005
This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous...Anonymous
September 18, 2005
This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous...Anonymous
September 19, 2005
This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous...Anonymous
July 26, 2006
As I had previously said I love extension methods&nbsp;and have started using them at multiple places...Anonymous
August 07, 2006
i want to print a windoe form on printer
whats this method?
thanksAnonymous
August 07, 2006
i want to print a window form on printer
whats this method?
thanksAnonymous
September 06, 2006
&nbsp;Jim Wooley, leader of the Atlanta Visual Basic Study Group, presented to the Atlanta C# User Group...Anonymous
September 06, 2006
&nbsp;Jim Wooley, leader of the Atlanta Visual Basic Study Group, presented to the Atlanta C# User Group...Anonymous
February 22, 2007
I love extension methods.for "int[] a = new int[] {1, 2, 2, 4, 3};", you can write this with C#3.0 : "int[] a = {1, 2, 2, 4, 3};" isn't it great?Anonymous
May 10, 2007
Really its an awesome thing. Its gonna be widely used. Many of us would face this problem of adding a new method to an existing class, so it will definitely be helpfull.Anonymous
August 03, 2007
Thanks for this article. I've included a bit more info on extension methods on my blog as well: http://www.iansuttle.com/blog/post/Extension-Methods-in-C-30.aspxAnonymous
August 12, 2007
Thanks. What happens when identical signatures clash?Anonymous
November 11, 2007
substr() vs String.Substring()Anonymous
November 21, 2007
Today I was spreading the goodness of Ruby and why I love it so much (and you can expect multiple postsAnonymous
November 21, 2007
Today I was spreading the goodness of Ruby and why I love it so much (and you can expect multiple postsAnonymous
December 23, 2007
Cool C# 3.0 Extension Method IdeaAnonymous
June 06, 2008
After the declaration of C# 3.0 I went ahead and installed the PDC bits . After reading through the language spec . I was very very very unhappy. I mean we were just getting excited over C#2.0 supporting generics, anonymous mehtods, Nullable types anAnonymous
September 17, 2008
PingBack from http://mattgrande.wordpress.com/2008/09/17/solving-multiple-inheritance-in-c-30/Anonymous
January 21, 2009
PingBack from http://www.keyongtech.com/572995-how-can-i-create-aAnonymous
March 03, 2009
PingBack from http://blog.dragonsoft.us/2009/03/03/crystal-reports-extension-methods-library/