Search This Blog

2009-05-31

C# 3.0 Tutorial -2:Extension Methods

In the beginning – that is, in C# 1.0 – the methods belonging to a class were defined within the body of the class. C# 2.0 changed that somewhat. By introducing partial classes, the methods making up a class could be defined in more than one place. However, they were all collected together at compile time, so it was nothing particularly new. Anonymous methods were something new, however. Conceptually, anonymous methods are associated with no class at all. C# 3.0 continues the journey with extension methods.
Extension methods are associated with a class (either a specific one or they are generic and can work for any class). What makes them different from normal instance methods is that they are not defined within the class itself. Instead, they are defined in some other static class. This all sounds rather strange, so let’s take an example.
Imagine that we had got some third party class library for computing a serial number for a product from a product ID and some user details. The method may take the arguments ProductID, CustomerName, CustomerDateOfBirth, and CustomerCountry. In the class library, its implementation may look something like this:

public sealed class CodeGenerator
{
public long generateCode(int ProductID, string CustomerName, DateTime CustmerDOB, string CustomerCountry)
{
return (ProductID % 42) + CustomerName.GetHashCode() * (CustmerDOB.Ticks - CustomerCountry.GetHashCode());

}
}

In our application, however, we pass around user data in a structure.

struct UserInfo
{
public int UserID;
public string Name;
public DateTime DOB;
public string CountryCode;
}

Obj is used in two ways. The first is that it refers to the v-table. This can be used to look up the method to call (in the case of method overriding). The second use is that it is passed as the first parameter to the method. This parameter is taken and becomes the "this" variable – this is what the CLR does under the hood. So essentially, all of your instance methods have an implicit first parameter that the C# compiler inserts for you and provides access to through the "this" variable.

Second, there is an alternative way of thinking about object orientation: rather than having a class-based system, you can use multi-methods. Multi-methods are very similar to method overloading in C# - you can have methods with the same name but different signatures, and the right one is invoked depending on the parameters that are used in the call. Now imagine that the implicit first parameter that we just discussed is not implicit, but instead you place it at the start of every method's parameter list. The type of that first parameter can be a class name. When deciding which method to call, the full signature (including the type of the invocant – the first parameter) is taken into account. That means that you can write methods for a particular class anywhere you like in your program, or extend existing classes with your own methods.

Sometimes the object a method is being called on is referred to as the invocant. For example, in obj.method(), obj is the invocant.If you can get your head around those ideas, then you will find extension methods fairly straightforward. An extension method is a static method, but with the first parameter it takes being explicitly marked as receiving the object that the method was called on. Extension methods may only appear in static classes. Returning to our example, we can implement an extension method like this:

static class MyExtensions
{
public static long generateCode(this CodeGenerator CG, int ProductID, UserInfo User)
{
return 2 + 3;
}
public static long generateCode(this CodeGenerator CG)
{
return 2 + 3 + 4;
}

}

Now run the following code from your page load event
CodeGenerator CG = new CodeGenerator();
UserInfo User = new UserInfo();
User.UserID = 453;
User.Name = "Manab";
User.DOB = DateTime.Now;
User.CountryCode = "UK";


long Code = CG.generateCode(5183, "Manab", DateTime.Now, "UK");
long Code2 = CG.generateCode(5183, User);
long Code3 = CG.generateCode();
Response.Write(Code + "<br/>");
Response.Write(Code2 + "<br/>");
Response.Write(Code3 + "<br/>");

Output :
4605813284442487372
5
9

Another question that comes up is that of performance. Does the runtime have to locate the method to call at runtime, or is it worked out at compile time? The answer is that it is decided at compile time, so there is not any runtime dispatch overhead. In fact, the lookup doesn't even go through the v-table, so it may well be faster than some instance method calls. (For those who like to have the details, the .Net CLR provides an instruction, named "call", for calling a method without consulting the v-table, which the compiler can use instead of the standard one when it knows that it is safe to do so).

Perhaps the most important question, though, is when extension methods should be used. The C# designers themselves say that they are not something you want to be using all of the time, but rather in situations where instance methods are unable to provide what you need.

If you have a class and want to extend it with some special functionality that is specific to your usage of it, you now have two options.
Inherit from it and put the special functionality in the sub class
Write extension methods
The first option is preferable. Inheritance is well understood by other programmers, it is clear what method will be called and you won't have to repeatedly write the class name when writing the methods. So why the second option? I can think of a few cases.
If the class is sealed, you will be unable to inherit from it. In this case, you have no option but to use extension methods.
You may be using some kind of object factory that instantiates objects of a given class, but you do not have the ability to modify it so that your subclass is instantiated instead. Therefore extension methods are the only way to extend the functionality of these objects.
You want to implement a method that can be invoked on all classes implementing a given interface; before, we had no way to attach a method implementation to an interface.
You may want to add related things to a number of other classes, and from a software engineering point of view it may be better to collect those together in one place rather than spreading them amongst many classes.
If you find yourself writing extension methods every day, then that's probably a bad sign. It's a myth that every language feature is intended to be used equally often, both in real and programming languages.


A complete code is as follows.I have write this code in the aspx page of an Web application

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
public partial class CSharp3_ExtensionMethods : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CodeGenerator CG = new CodeGenerator();
UserInfo User = new UserInfo();
User.UserID = 453;
User.Name = "Manab";
User.DOB = DateTime.Now;
User.CountryCode = "UK";


long Code = CG.generateCode(5183, "Manab", DateTime.Now, "UK");
long Code2 = CG.generateCode(5183, User);
long Code3 = CG.generateCode();
Response.Write(Code + "<br/>");
Response.Write(Code2 + "<br/>");
Response.Write(Code3 + "<br/>");



A a1 = new A();
Response.Write("a1.useMe():" + a1.useMe() + "<br/>");

B b1 = new B();
Response.Write("b1.useMe():" + b1.useMe() + "<br/>");
Response.Write("b1.useMe(manab):" + b1.useMe("manab") + "<br/>");

A a2 = new A();
Response.Write("a2.useMe(manab) :" + a2.useMe("manab") + "<br/>");
}
}
struct UserInfo
{
public int UserID;
public string Name;
public DateTime DOB;
public string CountryCode;
}
public sealed class CodeGenerator
{
public long generateCode(int ProductID, string CustomerName, DateTime CustmerDOB, string CustomerCountry)
{
return (ProductID % 42) + CustomerName.GetHashCode() * (CustmerDOB.Ticks - CustomerCountry.GetHashCode());

}
}
static class MyExtensions
{
public static long generateCode(this CodeGenerator CG, int ProductID, UserInfo User)
{
return 2 + 3;
}
public static long generateCode(this CodeGenerator CG)
{
return 2 + 3 + 4;
}

}
//Create another example of extensions as belows
public class A
{
public string useMe()
{
return "I am in Class A ->useMe()";
}
}
public class B : A
{
/* public string useMe()
{
return "I am in Class B ->useMe()";
}*/
}
static class C
{
public static string useMe(this A a1, string str1)
{
return "I am in Class C ->useMe(this A a1,string str1)";
}
}
public class Jungle
{
public string Add(Monkey mn)
{
return mn.HelloMonkey();
}
}
public class Monkey
{
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string HelloMonkey()
{
return Name;
}
}

Output is as follows:

4605813284442487372
5
9
a1.useMe():I am in Class A ->useMe()
b1.useMe():I am in Class A ->useMe()
b1.useMe(manab):I am in Class C ->useMe(this A a1,string str1)
a2.useMe(manab) :I am in Class C ->useMe(this A a1,string str1)


tags:what is Extension Methods in C# 3.0/3.5,how can we implement Extension Methods in c# 3.0/3.5

No comments: