Using Extension Methods
Introduction
How often do you want to modify existing classes to have extra methods? Quite
often. Right? When you have source code of the classes under consideration at
your hand then things are easy. You probably just add the extra methods to those
classes. What if you don't have source code? Well. In such cases one approach is
to inherit the existing classes and add extra methods to the child classes.
However, this way may not be always correct and possible in terms of your
application design and OO principles. Luckily, C# offers a quick way to extend
your class functionality through a feature known as Extension Methods. Extension
methods allow you to extend existing types without inheriting them. This article
is going to throw some light on this handy feature.
Example Scenario
Let's try to undertand what extension methods are with an example.
Assume that you are developing a discussion forum application. The forum
displays date and time at which posts and replies are made. The discussion will
be used primarily in India and hence you wish to show these timestamps in Indian
Standard Time (IST). However, your servers are hosted in some different
geographical region (and hence date-time offset) and hence you must do some
adjustment to display all the times in IST.
You then decide to get the IST using the following lines of code:
DateTime dt=DateTime.Now;
DateTime utc = dt.ToUniversalTime();
DateTime ist = utc.AddMinutes(330);
The above code calls ToUniversalTime() method of the DateTime structure that
returns date and time in Universal Standard Time (earlier known as GMT). You
then add 330 minutes (5 hrs. 30 min.) to the UTC and get IST. Though the code is
simple enough and your team can call it wherever they need, won't it be nice if
you can have this functionality to DateTime structure itself? That way all team
members will find it convenient to quickly get the IST from a specified time.
This is where we will use a C# extension method to get our job done.
Creating Extension Methods
Have a look carefully at the following class that defines two extension
methods:
namespace Utils
{
public static class DateTimeHelper
{
public static DateTime ToIST(this DateTime dt)
{
DateTime utc = dt.ToUniversalTime();
return utc.AddMinutes(330);
}
public static bool IsDate(this string s)
{
DateTime dt;
return DateTime.TryParse(s, out dt);
}
}
}
The above code defines a static class named DateTimeHelper. All the extension
methods must reside inside a static class. The extension methods themselves must
be static (In fact that is why compiler forces you to declare the class as
static).
The ToIST() static method is an extension method that returns a DateTime
instance. Observe how the parameter of the method is specified. An extension
method can have any number of parameters but the first parameter indicates the
data type to which that extension is applicable. In case of ToIST() method we
specify that this method is an extension method of DateTime structure. The ToIST()
method simply adjusts the date and time with required offset.
The IsDate() method is another extension method that will be applicable to
string data type. Inside it checks if the supplied string is a valid date and
returns a Boolean value.
Now, if you use DateTime structure then the Visual Studio will show you ToIST()
method in the IntelliSense. Similarly, IsDate() method will be shown for string
class.
Note that the extension methods will be shown for the underlying type only if
the class defining the extension methods is available to your application. That
means you must refer the appropriate assembly for DateTimeHelper class and
import its namespace before using the extension methods.
More about extension methods
Though extension methods allow you to quickly extend an existing type this
feature should not be used extensively as a replacement to other elegant
approaches. Additionally, the following points about extension methods are worth
noting.
- Extension methods can chain themselves. For example you may write
something like this:
dt.ToIST().ToDDMMYYYY()
The ToIST() and ToDDMMYYYY() are assumed to be extension methods.
- Extension methods can be accessed only when its namespace is in scope
- If an extension method has the same signature as any of the instance
method of the class it extends then the instance methods take precedence
- If two extension methods of a type have same signature them they must be
called like normal static methods. For example, if you define two extension
methods with same name and signature in two classes say DateTimeHelper1 and
dateTimeHelper2, then they can be called like this -
DateTimeHelper1.ToIST(dt)
That's it! Will be back with something interesting. Till then keep coding!