Register   |  Login
You are hereBlogs
 Bloggers
 Featured Blogs
 Blogs
 Recent Articles
 Recent Interview Question
 Blogs
Apr 2

Written by: Karuna Kammari
4/2/2009 12:08 AM 

 Feel the joy of new things.. :)

 

One thing i love in Orcas is feature of extension methods.
This is one of the C#3.0 language fatures.

This feature helps the developer to add there own custom methods as members of a class instance
apart from the class what it have and they can be used across the project as static methods.
These are just like the methods which we write in a common utility class to use across our project.

For example, a utility class for having custom regular expressions methods like

   public static bool IsValidEmailAddress(string value)
      {
          Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
          return regex.IsMatch(value);
      }

Extension methods also serve the same, but in different way of writing the method and also it exists as member of class instance rather
than class.

For example, a custom method to test weather a string is null or empty without using existing IsNullOrEmty() of Sting class.

      public static bool NullOrEmptyString(this string value)
      {
          if (value == null && value == "")
          {
              return true;
          }
          else
          {
              return false;
          }
      }


The above method looks like most common way of writing our normal staic methods. but here is minor change .i.e string 'this' in brackets after method name.
This is required to make methodas extension method.

But we can find the real beauty of extension methods when we write methods to be exists as part of an interface

When we talk about interfces in C#, there is always different openions among producer of the interfce,
Implementor of the interface and the Consumer of the interace.

Producer of interface just gives away the public interface not much worrying about how rich or small it is.
The Implementor of the interface want the interface as small as possible. where as the Consumer of the interface always
want the interface look as rich as possible.

The technique of Extension methods acn be used to satisfy above openions.

With this the interace need not have all the methods which consumer wants. Instead the interface implementor(project)
can have a static class. this class servers as interface extension and contain all custom methods which consumer want as members of the interface.

For example i can write a simple ICollection interface in which i want to have a method IsEmpty() to check whether the collection is empty or not.

Now i can have my ICollection interface simply look like this.

public interface ICollectionTwo
    {
       int Count { get; set; }

       //int this[int index] { get; }

       ICollectionImplementor this[int index] { get; } //indexer

       bool IsEmpty();//one interface method

       bool IsEpmty2();//one more similar kind of inteface
    }


Now implentor of above interface feels very comfortable to implement it as he always looks the interface is as stinct as possible.
But as i said above, the consumer alwas expects the interface as rich as possible. So he feels like it would be better if the interface
have one more method, lets say suppose IsEmpty2().

But for the implementer of the above interface, its required to implement both methods 'IsEmpty()' and 'IsEpmty2()'. Now each and every
implentor of the aboe interface would require to implement he above methods. This is hectic as far as mplementor is concerned.

This can be solved with the use of extension methods. The consumer project can have a static class wich can have the above mentioned two
methods as static methods. Now these methods will still be treated and appears as members of the interface. So any class wchich implement
the above interface need not require to implement all the methods.

So i can write the above interface as

public interface ICollectionTwo
    {
       int Count { get; set; }

       //int this[int index] { get; }

       ICollectionImplementor this[int index] { get; } //indexer

       //bool IsEmpty();//one interface method

       //bool IsEpmty2();//one more similar kind of inteface
    }

Note that in above interface i commented the two methods.

The implementor class of the interface can be written as.

 public class ICollectionImplementor : ICollectionTwo
    {
       private int count;
       public int Count { get { return count; } set { count = value; } }
       public ICollectionImplementor this[int index] { get { return new ICollectionImplementor (); } }

       public ICollectionImplementor()
       { }

       public void ExtraMethod()
       {
      
       }
    }

Here i write one ore class which implement the same interface.

 public class ICollectionImplementorTwo : ICollectionTwo
    {
       private int count;
       public int Count { get { return count; } set { count = value; } }
     
       public ICollectionImplementorTwo this[int index] { get { return new ICollectionImplementorTwo(); } }

       public ICollectionImplementorTwo()
       { }

       public void ExtraMethodTwo()
       {
      
       }
    }


Now i need to write the static class(should be static) to have above two methods. This is can be treated as extesnion class for the above interface.

so the class can written as below.

 public static class ICollectionTwoExtension
    {
        //Extension method IsEmpty for interface ICollectionTwo.
      public static bool IsEmpty(this ICollectionTwo c) // observe here 'this ICollectionTwo c'
       {
           return c.Count == 0;
       }    

      //Extension method IsEmpty2 for interface MyICollection
      public static bool IsEmpty2(this ICollectionTwo c) // observe here 'this ICollectionTwo c'
      {
          return c.Count == 0;
      }

       //String instance IsValidEmailAddress
      public static bool IsValidEmailAddress(this string value)
      {
          Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
          return regex.IsMatch(value);
      }
      
    }

Observe the two method definitions IsEmpty(), IsEmpty2() above. Firts af all the class should be statc and methods should be static .
and the parameters in the method should start with keyword 'this' followed by interface name.  Then it is an extension method for the interface

combine all classes and interface above and write the client code to use the extension methods.


now cleint code can use the above static class to get the two methods as members of interface methods.

Here the client(consumer) code goes as,

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           

            //**********Testing ICollectionImplementor***********************
            //Here client(consumer) ICollectionImplementor want only one method IsEmpty().
            //Thus it doesn't look at interface ICollectionTwo, as rich as.

            //Cretae instance of ICollectionImplementor
            ICollectionImplementor iCollectionImplementor = new ICollectionImplementor();

            //Set Count property to some value.
            iCollectionImplementor.Count = 1;
 
            for (int i = 0; i < iCollectionImplementor.Count; i++)
            {
                if (iCollectionImplementor[i].IsEmpty())
                {
                    MessageBox.Show("IsEmpty is called with iCollectionImplementor  instance");
                }
            }

            //************Testing ICollectionImplementorTwo **********************
            //Here client(consumer) want ICollectionImplementorTwo to have two methods IsEmpty() and IsEmpty2().
            //Thus looking at interface 'ICollectionTwo' as rich as possible

            //Cretae instance of MyICollectionImplementorTwo
            ICollectionImplementorTwo iCollectionImplementorTwo = new ICollectionImplementorTwo();

            //Set Count property to some value.
            iCollectionImplementorTwo.Count = 1;

            for (int i = 0; i < iCollectionImplementorTwo.Count; i++)
            {
                if (iCollectionImplementorTwo[i].IsEmpty())
                {
                    MessageBox.Show("IsEmpty is called with iCollectionImplementorTwo  instance");
                }

                if (iCollectionImplementorTwo[i].IsEmpty2())
                {
                    MessageBox.Show("IsEmpty2 is called with iCollectionImplementorTwo  instance");
                }
            }                 
           
        }
    }

The above i am using simple winform application for using the interface extension methods.

if you look at the above two methods, they appear as members of the interface rather than the static class.

thus client project can add as many as extension methods as it want to be as memebrs of interface without requiring the implemetor class
to implement the methods. still they can apear as members of interface.

That is the power of extension methods.

Happy coding... -:)

Karuna..

 

 

 

 

Tags:

Your name:
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment   Cancel 
 Blogs
 You may be interested