Share via


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&amp;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?
    thanks

  • Anonymous
    August 07, 2006
    i want to print a window form  on printer
    whats this method?
    thanks

  • Anonymous
    September 06, 2006
    &amp;nbsp;Jim Wooley, leader of the Atlanta Visual Basic Study Group, presented to the Atlanta C# User Group...

  • Anonymous
    September 06, 2006
    &amp;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.aspx

  • Anonymous
    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 posts

  • Anonymous
    November 21, 2007
    Today I was spreading the goodness of Ruby and why I love it so much (and you can expect multiple posts

  • Anonymous
    December 23, 2007
    Cool C# 3.0 Extension Method Idea

  • Anonymous
    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 an

  • Anonymous
    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-a

  • Anonymous
    March 03, 2009
    PingBack from http://blog.dragonsoft.us/2009/03/03/crystal-reports-extension-methods-library/