Extension methods

Tue, May 20, 2008 4-minute read

As promised way back in 2007 I will try to show some of the coolness of extension methods.

Extension methods are simply said, methods that can extend existing classes whether or not you have access to the original code.

You cannot access private member variables etc, but from all other views and use it will look as it was a method that was created originally in the class it self.

To use an extension method, you have to import the namespace that contains the class with the method, and have a variable of the type the method works on.

Lets say you always wanted a Reverse() method on a string because you always use that nice feature in some obscure project you are the maintainer of.

No sweat.

The principles of extension methods are simple. Just create a static class, put a static method in that class, with a special signature, and voilá you can access that method in your other class as it was natively written for that.

Let me give you an example with the Reverse() method on string.

/// <summary>
/// Class with useful extensions to System.String
/// </summary>
public static class StringExtensions
{
    /// <summary>
    /// Reverses the specified string
    /// </summary>
    /// <param name="s">The s.</param>
    /// <returns></returns>
    public static string Reverse(this string s)
    {
        StringBuilder sb = new StringBuilder(s.Length);
        char[] chars = s.ToCharArray();
        for (int x = chars.Length - 1; x > -1; x--)
        {
            sb.Append(chars[x]);
        }
        return sb.ToString();
    }
}

Please note the use of this in the method signature, the this signifies that its should be interpreted as an extension method, and then you just use the parameter as it was a normal method.

To use the method above, just create a string variable and call Reverse() on it.

Just as easy as:

string s = "OMG";
Console.WriteLine(s.Reverse());

And its really as simple as that.

Another example could be System.DateTime which sometimes can be a bitch to get to know the different string formats for outputting. Why not just create an extension method with your favorite format:

/// <summary>
/// Class with useful extensions to System.DateTime
/// </summary>
public static class DateTimeExtensions
{
    /// <summary>
    /// Returns an ISO8601 string representation of the date time object
    /// as used in e.g. VEVENT
    /// </summary>
    /// <param name="dt">The dt.</param>
    /// <returns></returns>
    public static string ToISO8601String(this DateTime dt)
    {
        if (dt.Kind == DateTimeKind.Utc)
        {
            return dt.ToString("yyyyMMddThhmmssZ");
        }
        else
        {
            return dt.ToString("yyyyMMddThhmmss");
        }
    }
}

Which in turn is used as easily as:

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToISO8601String());

See how easy it is 😃

Extension methods can naturally have parameters just like normal methods, and its as simple as creating normal parameters, the only rule is to have the class that the method should be an extension to as the first parameter, i.e. public static bool MatchModulus(this int x, int modulus).

A more elaborate example could be another string extention method called Slice:

/// <summary>
/// Slices the specified string into the specified number of parts
/// </summary>
/// <param name="s">The string to slice into parts</param>
/// <param name="parts">The number of parts</param>
/// <returns></returns>
public static string[] Slice(this string s, int parts)
{
    if (string.IsNullOrEmpty(s))
    {
        throw new ArgumentException("String to be sliced cannot be null or empty");
    }
    if (parts < 1)
    {
        throw new ArgumentException("Number of parts to slice into must be greater than 0");
    }
    
    string[] slices = new string[parts];
    int charsInSlice = (int)s.Length / parts;
    int charsRemoved = 0;
    for (int x = 0; x < parts; x++)
    {
        slices[x] = s.Substring(charsRemoved, charsInSlice);
        charsRemoved += charsInSlice;
    }
    
    if (charsRemoved != s.Length)
    {
        slices[parts - 1] += s.Substring(charsRemoved);
    }

    return slices;
}

Which in this example slices the string into the specified number of parts. The example is not a perfect method, because if you specify more parts than characters in the string it will return a string array with only the last element of the string array containing the entire string. Feel free to rewrite the method, its very simple to change :-p.

I hope this gave a little insight into extension methods and that they can in fact be useful.